/* TV365 Cloud — 2035 interaction layer (presentation only).
   Every rule here is scoped to html[data-ui-version="2035"]. Remove that attribute (or the two tags in
   index.html) and the portal is exactly its legacy self: nothing below reaches the API, state or payloads.
   Motion rules: transforms and opacity only (composited); a box-shadow or gradient paints once per interaction,
   never per frame on more than the one element being touched. theme.css already stops all motion under
   prefers-reduced-motion; ui2035.js does the same for its own effects. The toggle itself is unscoped: it has to
   be clickable in Legacy too. Colours are the theme tokens, so every theme and the Brand palette are covered. */

/* registered properties: the focus sweep animates them (Chrome, Edge, Safari 16.4+, Firefox 128+) */
@property --ui-sweep { syntax: '<number>'; inherits: false; initial-value: 0; }
@property --ui-halo  { syntax: '<number>'; inherits: false; initial-value: 0; }

/* ======================================================= tokens ======================================================= */
html[data-ui-version="2035"] {
  --ui-ease-sink: cubic-bezier(.16, 1, .3, 1);          /* press: instant, decelerating */
  --ui-ease-spring: cubic-bezier(.34, 1.56, .64, 1);    /* release: elastic, overshoots */
  --ui-ease-roll: cubic-bezier(.76, 0, .24, 1);         /* digits: fast through the middle, weighted stop */
  --ui-ease-momentum: cubic-bezier(.22, 1, .36, 1);     /* panels: quintic ease-out */
  --ui-lift-shadow: 0 22px 44px -14px rgba(0, 0, 0, .45), 0 4px 12px -4px rgba(0, 0, 0, .25);
}

/* ================================================ 1. buttons: sink & spring ============================================= */
html[data-ui-version="2035"] .btn,
html[data-ui-version="2035"] button.tb-chip,
html[data-ui-version="2035"] .seg > button,
html[data-ui-version="2035"] .p-tabs > button,
html[data-ui-version="2035"] .key,
html[data-ui-version="2035"] .round,
html[data-ui-version="2035"] .pe-btn,
html[data-ui-version="2035"] .tvs-btn,
html[data-ui-version="2035"] .mp-arrow,
html[data-ui-version="2035"] .tb-pop .item,
html[data-ui-version="2035"] .nav-leaf,
html[data-ui-version="2035"] .nav-group > button,
html[data-ui-version="2035"] .nav-sub > button {
  position: relative;
  -webkit-tap-highlight-color: transparent;
  transition: transform 420ms var(--ui-ease-spring), background-color .15s, border-color .15s, color .15s, box-shadow .2s;
}
/* the password eye is absolutely placed inside its box by theme.css: it springs, but its position is never touched */
html[data-ui-version="2035"] .pw-eye { -webkit-tap-highlight-color: transparent; transition: transform 420ms var(--ui-ease-spring), background-color .15s, color .15s; }
/* the inner ambient-occlusion layer: a fixed inset shadow whose opacity is animated (composited) */
html[data-ui-version="2035"] .btn::after,
html[data-ui-version="2035"] button.tb-chip::after,
html[data-ui-version="2035"] .seg > button::after,
html[data-ui-version="2035"] .p-tabs > button::after,
html[data-ui-version="2035"] .key::after,
html[data-ui-version="2035"] .round::after,
html[data-ui-version="2035"] .pe-btn::after,
html[data-ui-version="2035"] .tvs-btn::after,
html[data-ui-version="2035"] .tb-pop .item::after,
html[data-ui-version="2035"] .nav-leaf::after,
html[data-ui-version="2035"] .nav-group > button::after,
html[data-ui-version="2035"] .nav-sub > button::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; opacity: 0;
  box-shadow: inset 0 2px 8px rgba(0, 0, 0, .30), inset 0 0 0 1px rgba(0, 0, 0, .10);
  transition: opacity 140ms var(--ui-ease-sink);
}
/* press: 94 % at once, shadow dims the face */
html[data-ui-version="2035"] .btn:active:not(:disabled),
html[data-ui-version="2035"] button.tb-chip:active,
html[data-ui-version="2035"] .seg > button:active,
html[data-ui-version="2035"] .p-tabs > button:active,
html[data-ui-version="2035"] .key:active,
html[data-ui-version="2035"] .round:active:not(:disabled),
html[data-ui-version="2035"] .pe-btn:active,
html[data-ui-version="2035"] .tvs-btn:active,
html[data-ui-version="2035"] .mp-arrow:active:not(:disabled),
html[data-ui-version="2035"] .tb-pop .item:active,
html[data-ui-version="2035"] .nav-leaf:active,
html[data-ui-version="2035"] .nav-group > button:active,
html[data-ui-version="2035"] .nav-sub > button:active,
html[data-ui-version="2035"] .pw-eye:active {
  transform: scale3d(.94, .94, 1);
  transition-duration: 90ms;
  transition-timing-function: var(--ui-ease-sink);
}
html[data-ui-version="2035"] .btn:active:not(:disabled)::after,
html[data-ui-version="2035"] button.tb-chip:active::after,
html[data-ui-version="2035"] .seg > button:active::after,
html[data-ui-version="2035"] .p-tabs > button:active::after,
html[data-ui-version="2035"] .key:active::after,
html[data-ui-version="2035"] .round:active:not(:disabled)::after,
html[data-ui-version="2035"] .pe-btn:active::after,
html[data-ui-version="2035"] .tvs-btn:active::after,
html[data-ui-version="2035"] .tb-pop .item:active::after,
html[data-ui-version="2035"] .nav-leaf:active::after,
html[data-ui-version="2035"] .nav-group > button:active::after,
html[data-ui-version="2035"] .nav-sub > button:active::after { opacity: 1; }
/* release: ui2035.js stamps data-ui-spring on pointer-up / Enter / Space; 94 % → 102 % → 100 % */
@keyframes ui-spring {
  0%   { transform: scale3d(.94, .94, 1); animation-timing-function: cubic-bezier(.22, 1, .36, 1); }
  45%  { transform: scale3d(1.02, 1.02, 1); animation-timing-function: cubic-bezier(.34, 1.56, .64, 1); }
  100% { transform: none; }
}
html[data-ui-version="2035"] [data-ui-spring] { animation: ui-spring 420ms both; }
/* The eye button in password boxes is centred with transform: translateY(-50%) (theme.css .pw-eye). A press or spring
   that replaces the transform drops the button half its height under the pointer, the release lands beside it and the
   click never reaches the button, so the password stayed hidden. Keep the centring in every frame. */
html[data-ui-version="2035"] .pw-eye:active { transform: translateY(-50%) scale3d(.94, .94, 1); }
@keyframes ui-spring-pw {
  0%   { transform: translateY(-50%) scale3d(.94, .94, 1); animation-timing-function: cubic-bezier(.22, 1, .36, 1); }
  45%  { transform: translateY(-50%) scale3d(1.02, 1.02, 1); animation-timing-function: cubic-bezier(.34, 1.56, .64, 1); }
  100% { transform: translateY(-50%); }
}
html[data-ui-version="2035"] .pw-eye[data-ui-spring] { animation-name: ui-spring-pw; }
/* a primary button lifts a little under the pointer (one shadow paint, static afterwards) */
html[data-ui-version="2035"] .btn-primary:hover:not(:disabled),
html[data-ui-version="2035"] .btn-danger:hover:not(:disabled) { box-shadow: 0 8px 18px -10px currentColor; }
html[data-ui-version="2035"] .btn-primary:hover:not(:disabled) { box-shadow: 0 8px 18px -10px var(--blue); }
html[data-ui-version="2035"] .btn-danger:hover:not(:disabled) { box-shadow: 0 8px 18px -10px var(--red); }

/* ============================================= 2. navigation: momentum & chevrons ======================================= */
html[data-ui-version="2035"] .nav-group > button .chev,
html[data-ui-version="2035"] .nav-sub > button .chev { transition: transform 380ms var(--ui-ease-spring); }
html[data-ui-version="2035"] .nav-leaf { transition: transform 220ms var(--ui-ease-momentum), background-color .15s, color .15s, box-shadow .2s; }
html[data-ui-version="2035"] .nav-leaf:hover:not(.active) { transform: translate3d(3px, 0, 0); }
html[data-ui-version="2035"] .nav-leaf.active { box-shadow: inset 3px 0 0 var(--blue); }
/* a sub-menu opening: 80 % of the way in 150 ms, the last 20 % glides over 300 ms */
@keyframes ui-momentum {
  0%       { opacity: 0; transform: translate3d(0, 14px, 0) scale3d(.985, .985, 1); animation-timing-function: cubic-bezier(.22, 1, .36, 1); }
  33.333%  { opacity: 1; transform: translate3d(0, 2.8px, 0) scale3d(.997, .997, 1); animation-timing-function: cubic-bezier(.22, 1, .36, 1); }
  100%     { opacity: 1; transform: none; }
}
@keyframes ui-momentum-y {
  0%       { opacity: 0; transform: translate3d(0, -8px, 0); animation-timing-function: cubic-bezier(.22, 1, .36, 1); }
  33.333%  { opacity: 1; transform: translate3d(0, -1.6px, 0); animation-timing-function: cubic-bezier(.22, 1, .36, 1); }
  100%     { opacity: 1; transform: none; }
}
@keyframes ui-fade { from { opacity: 0; } to { opacity: 1; } }
html[data-ui-version="2035"] .nav-children { animation: ui-momentum-y 450ms both; transform-origin: top left; }
html[data-ui-version="2035"] .tb-pop { animation: ui-momentum 450ms both; transform-origin: top right; }
html[data-ui-version="2035"] .side.open { transition: transform 450ms var(--ui-ease-momentum), box-shadow .3s; }

/* ============================================== 3. cards, dialogs, toasts ============================================== */
html[data-ui-version="2035"] .overlay { animation: ui-fade 300ms var(--ui-ease-momentum) both; }
html[data-ui-version="2035"] .modal { animation: ui-momentum 450ms both; transform-origin: 50% 60%; }
html[data-ui-version="2035"] .toast { animation: ui-momentum 450ms both; }
/* page cards arrive with a short stagger; the shadow is the theme's own, painted once */
html[data-ui-version="2035"] .content .card,
html[data-ui-version="2035"] .content .dv-card,
html[data-ui-version="2035"] .content .p-stat { animation: ui-momentum 450ms both; }
html[data-ui-version="2035"] .content .card:nth-child(2),  html[data-ui-version="2035"] .content .dv-card:nth-child(2)  { animation-delay: 30ms; }
html[data-ui-version="2035"] .content .card:nth-child(3),  html[data-ui-version="2035"] .content .dv-card:nth-child(3)  { animation-delay: 60ms; }
html[data-ui-version="2035"] .content .card:nth-child(4),  html[data-ui-version="2035"] .content .dv-card:nth-child(4)  { animation-delay: 90ms; }
html[data-ui-version="2035"] .content .card:nth-child(5),  html[data-ui-version="2035"] .content .dv-card:nth-child(5)  { animation-delay: 120ms; }
html[data-ui-version="2035"] .content .card:nth-child(6),  html[data-ui-version="2035"] .content .dv-card:nth-child(6)  { animation-delay: 150ms; }
html[data-ui-version="2035"] .content .card:nth-child(n+7), html[data-ui-version="2035"] .content .dv-card:nth-child(n+7) { animation-delay: 180ms; }
/* a card inside a card (KPI tiles in a panel) has already arrived with its parent */
html[data-ui-version="2035"] .content .card .card { animation: none; }
html[data-ui-version="2035"] .card { transition: box-shadow .25s, border-color .15s; }

/* ============================================ 4. drag & drop: lift & displace ========================================== */
/* ui2035.js stamps data-ui-lift on the grabbed row / card for the length of the drag */
html[data-ui-version="2035"] [data-ui-lift] {
  transform: scale3d(1.05, 1.05, 1) !important;
  box-shadow: var(--ui-lift-shadow) !important;
  opacity: .92 !important;
  position: relative; z-index: 3;
  transition: transform 220ms var(--ui-ease-momentum), box-shadow 220ms ease, opacity 150ms !important;
}
html[data-ui-version="2035"] tr[data-ui-lift] > td { background: var(--card); }
/* the neighbours open the slot before the drop lands (dashboard widgets, platform menu picker) */
html[data-ui-version="2035"] .dv-card { transition: transform 300ms var(--ui-ease-momentum), border-color .15s, opacity .15s, box-shadow .2s; }
html[data-ui-version="2035"] .dv-card.drop-before { transform: translate3d(14px, 0, 0); box-shadow: var(--shadow), -3px 0 0 var(--blue); }
html[data-ui-version="2035"] .dv-card.drop-after  { transform: translate3d(-14px, 0, 0); box-shadow: var(--shadow), 3px 0 0 var(--blue); }
html[data-ui-version="2035"] .mp-row, html[data-ui-version="2035"] .mp-group { transition: transform 300ms var(--ui-ease-momentum), box-shadow .2s; }
html[data-ui-version="2035"] .mp-drop-before { transform: translate3d(0, 6px, 0); }
html[data-ui-version="2035"] .mp-drop-after  { transform: translate3d(0, -6px, 0); }
html[data-ui-version="2035"] .mp-drop-left   { transform: translate3d(8px, 0, 0); }
html[data-ui-version="2035"] .mp-drop-right  { transform: translate3d(-8px, 0, 0); }
html[data-ui-version="2035"][dir="rtl"] .dv-card.drop-before { transform: translate3d(-14px, 0, 0); }
html[data-ui-version="2035"][dir="rtl"] .dv-card.drop-after  { transform: translate3d(14px, 0, 0); }
/* lists that re-order live while dragging (call routes, test steps): ui2035.js slides each row from its old
   place to its new one (FLIP) with this curve; nothing jumps */
html[data-ui-version="2035"] [data-ui-flip] { transition: transform 300ms var(--ui-ease-momentum); }

/* ========================================== 5. textboxes: luminescent horizon =========================================== */
/* a 1 px ring streams around the box from where it was clicked (--ui-x / --ui-y, set by ui2035.js), then settles into
   a soft halo. The gradient repaints only while this one box is in its 700 ms sweep. Needs @property (data-ui-prop,
   set by the script when the browser has it); other browsers keep the theme's own focus ring. */
html[data-ui-version="2035"] .input,
html[data-ui-version="2035"] .side-search input { transition: border-color .15s, box-shadow .25s var(--ui-ease-momentum); }
@keyframes ui-horizon {
  0%   { --ui-sweep: 0;   --ui-halo: 0; animation-timing-function: cubic-bezier(.22, 1, .36, 1); }
  70%  { --ui-sweep: 1;   --ui-halo: .4; }
  100% { --ui-sweep: 1;   --ui-halo: 1; }
}
html[data-ui-version="2035"][data-ui-prop] .input:focus,
html[data-ui-version="2035"][data-ui-prop] .side-search input:focus {
  outline: none;
  border-color: transparent;
  background:
    linear-gradient(var(--input-bg), var(--input-bg)) padding-box,
    conic-gradient(from -90deg at var(--ui-x, 50%) var(--ui-y, 50%),
      var(--blue) 0turn,
      var(--blue) calc(var(--ui-sweep) * 1turn),
      color-mix(in srgb, var(--blue) 35%, transparent) calc(var(--ui-sweep) * 1turn + .02turn),
      transparent calc(var(--ui-sweep) * 1turn + .06turn),
      transparent 1turn) border-box;
  background-color: var(--input-bg);   /* the shorthand above clears it, and the list a <select> opens takes its colour from here */
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) calc(var(--ui-halo) * 28%), transparent);
  animation: ui-horizon 700ms both;
}
html[data-ui-version="2035"][data-ui-prop] .side-search input:focus { background-color: transparent; }
/* the typed character's landing trail (ui2035.js places one per keystroke; transform + opacity only) */
.ui2035-ghost {
  position: fixed; z-index: 9998; pointer-events: none; white-space: pre;
  will-change: transform, opacity;
  animation: ui-drop 170ms cubic-bezier(.22, 1, .36, 1) both;
}
@keyframes ui-drop { from { opacity: .9; transform: translate3d(0, -4px, 0); } to { opacity: 0; transform: none; } }

/* ============================================= 6. numbers: kinetic roll ================================================ */
/* ui2035.js hides the real figure (same box, same layout) and rolls a copy over it, digit by digit */
html[data-ui-version="2035"] [data-ui-roll] { color: transparent !important; text-shadow: none !important; }
.ui2035-roll {
  position: fixed; z-index: 9997; pointer-events: none; display: inline-flex; align-items: stretch;
  white-space: pre; overflow: hidden; text-align: left;
}
.ui2035-roll > span { display: inline-block; overflow: hidden; text-align: center; }
.ui2035-roll .ui2035-track { display: block; will-change: transform; transition: transform 520ms cubic-bezier(.76, 0, .24, 1); }
.ui2035-roll .ui2035-track > span { display: block; }
/* tabular figures on the counters that roll most, so a change never shifts its neighbours */
html[data-ui-version="2035"] .kpi .v, html[data-ui-version="2035"] .p-stat b, html[data-ui-version="2035"] .dv-value,
html[data-ui-version="2035"] .cf-kpi b, html[data-ui-version="2035"] .p-count, html[data-ui-version="2035"] .on-stat b,
html[data-ui-version="2035"] .ad-stat b { font-variant-numeric: tabular-nums; }
html[data-ui-version="2035"] .p-count { transition: transform 420ms var(--ui-ease-spring), background-color .2s; }
html[data-ui-version="2035"] .p-count[data-ui-roll] { transform: scale3d(1.12, 1.12, 1); }

/* ============================================ 7. verification toggle (unscoped) ========================================= */
.ui2035-toggle {
  position: fixed; left: 14px; bottom: 14px; z-index: 70;
  display: inline-flex; align-items: center; gap: 8px; height: 34px; padding: 0 12px 0 8px; margin: 0;
  border-radius: 999px; border: 1px solid var(--line, #d0d7e2); background: var(--card, #fff); color: var(--ink, #0f2a4a);
  font: 600 12px/1 Inter, system-ui, sans-serif; letter-spacing: .02em; cursor: pointer; user-select: none;
  box-shadow: var(--shadow-l, 0 10px 30px rgba(0, 0, 0, .3)); -webkit-tap-highlight-color: transparent;
  transition: transform 420ms cubic-bezier(.34, 1.56, .64, 1), box-shadow .2s, border-color .15s;
}
.ui2035-toggle:hover { border-color: var(--blue, #1f6feb); }
.ui2035-toggle:active { transform: scale3d(.94, .94, 1); transition-duration: 90ms; }
.ui2035-toggle:focus-visible { outline: none; box-shadow: var(--focus, 0 0 0 3px rgba(31, 111, 235, .35)); }
.ui2035-toggle .sw { position: relative; width: 30px; height: 18px; border-radius: 999px; background: var(--off-bg, #c9d1dc); transition: background-color .25s; flex: none; }
.ui2035-toggle .sw::after {
  content: ''; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .35); transition: transform 320ms cubic-bezier(.34, 1.56, .64, 1);
}
.ui2035-toggle[aria-pressed="true"] .sw { background: var(--blue, #1f6feb); }
.ui2035-toggle[aria-pressed="true"] .sw::after { transform: translate3d(12px, 0, 0); }
.ui2035-toggle .lbl { min-width: 44px; text-align: left; }
.ui2035-toggle small { font-weight: 500; color: var(--ink-3, #6b7f99); }
@media (max-width: 480px) { .ui2035-toggle { bottom: calc(10px + env(safe-area-inset-bottom, 0px)); left: 10px; height: 30px; } .ui2035-toggle small { display: none; } }
@media print { .ui2035-toggle, .ui2035-roll, .ui2035-ghost { display: none !important; } }
@media (prefers-reduced-motion: reduce) { .ui2035-ghost, .ui2035-roll { display: none !important; } }
