/* 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; }
/* 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;
  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; } }
