/* Menus v2 (owner, 2026-10-08): the map's menus — the top bar and the bottom toolbar only; the map
   is untouched. The old skin's colours stay exactly as they are ("keep the old colours, only the new
   frames, animations and transitions"): this file changes no background, text or fill colour. It
   adds frames, motion and transitions, and the motion is tinted with each element's own old accent
   (--tile). Every rule is scoped under html.menus-v2, which world.html always sets (it was the
   ?menus=v2 preview until the owner approved it). world/menus-fx.js adds the moving parts
   (.mv-trace, .mv-sweep, .mv-beam, ripples, value deltas) and the .mv-boot entry.

   What moves:
   - entry: the panels wipe in one after another, a bright edge leading;
   - idle: a beam crosses the toolbar now and then, a light runs along each group rule, the meters
     shimmer, the panel frames carry a slow running light;
   - hover: a light runs round the tile's frame, a sweep crosses its face, the label glitches and
     decrypts, the icon turns;
   - click: a ripple from the pointer;
   - armed (a sticky mode on): the frame light runs fast and the glow breathes;
   - a program switch: a load sweep across the card;
   - a number that changes: it flashes and a +N / −N floats off it;
   - a new feed line slides in. */

/* Performance: every looping effect moves only transform or opacity, which the browser runs on
   the GPU without repainting; a frame light that is not visible is paused. */

/* The old skin's accents, for the motion only. */
html.menus-v2 {
  --mv-cyan: #00fff5; --mv-green: #2bff8e; --mv-gold: #ffb01f; --mv-pink: #ff2fae; --mv-violet: #c496ff;
}

/* ---- The idle beam: a thin bright line with a faint trail crosses the toolbar every few seconds. ---- */
html.menus-v2 #toolbar { position: relative; }
html.menus-v2 .mv-beam {
  position: absolute; top: 0; bottom: 0; left: 0; width: 90px; pointer-events: none; z-index: 5;
  background: linear-gradient(90deg, transparent, rgba(0, 255, 245, 0.035) 75%, rgba(0, 255, 245, 0.45) 98%, transparent);
  animation: mv-beam 7s cubic-bezier(0.6, 0, 0.4, 1) infinite; opacity: 0;
}
@keyframes mv-beam { 0% { transform: translateX(-160px); opacity: 0; } 4% { opacity: 1; } 34% { opacity: 1; }
  38%, 100% { transform: translateX(calc(100vw + 20px)); opacity: 0; } }

/* ---- Top bar: an underline grows from the left on hover, in the button's own colour. ---- */
html.menus-v2 .bar-right .info-array button { overflow: hidden; transition: color 0.2s, border-color 0.2s, box-shadow 0.25s, letter-spacing 0.25s; }
html.menus-v2 .bar-right .info-array button::after {
  content: ''; position: absolute; left: 0; bottom: 0; height: 2px; width: 100%; background: currentColor;
  box-shadow: 0 0 8px currentColor; transform: scaleX(0); transform-origin: left; transition: transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1);
}
html.menus-v2 .bar-right .info-array button:hover { letter-spacing: 0.18em; }
html.menus-v2 .bar-right .info-array button:hover::after { transform: scaleX(1); }
html.menus-v2 #bar .live.on { animation: mv-live 2.4s ease-in-out infinite; }
@keyframes mv-live { 50% { opacity: 0.7; } }

/* ---- Panels: a frame in the old cyan line colour, carrying a slow running light. ---- */
html.menus-v2 #stats, html.menus-v2 .programs-panel {
  --tile: var(--mv-cyan); position: relative;
  border: 1px solid rgba(0, 255, 245, 0.16); border-radius: 4px; padding: 8px 10px; box-sizing: border-box;
}
html.menus-v2 #st-name { letter-spacing: 0.08em; }

/* The running light on a frame: a square conic gradient turns (transform only) behind a mask
   that leaves just the 1px border. The square is wide enough to cover the frame's diagonal. */
html.menus-v2 .mv-trace {
  position: absolute; inset: -1px; border-radius: inherit; padding: 1px; pointer-events: none; z-index: 3; overflow: hidden;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
  opacity: 0.55; transition: opacity 0.3s; animation-duration: 9s; /* read by ::before */
}
html.menus-v2 .mv-trace::before {
  content: ''; position: absolute; left: 50%; top: 50%; width: 160%; aspect-ratio: 1; margin: -80% 0 0 -80%;
  background: conic-gradient(transparent 0 72%, color-mix(in srgb, var(--tile) 60%, transparent) 86%, #fff 90%, transparent 93%);
  animation: mv-spin 9s linear infinite; animation-duration: inherit;
}
@keyframes mv-spin { to { transform: rotate(360deg); } }

/* Vitals: the old fills ease to their value, and a glint runs over them now and then. */
html.menus-v2 #nrg-meter-fill, html.menus-v2 #heat-meter-fill, html.menus-v2 .cr-meter-fill, html.menus-v2 #ram-seg-free {
  position: relative; overflow: hidden;
  transition: width 0.7s cubic-bezier(0.2, 0.8, 0.2, 1), flex-grow 0.7s cubic-bezier(0.2, 0.8, 0.2, 1);
}
html.menus-v2 #nrg-meter-fill::after, html.menus-v2 #heat-meter-fill::after, html.menus-v2 .cr-meter-fill::after, html.menus-v2 #ram-seg-free::after {
  content: ''; position: absolute; top: 0; bottom: 0; left: 0; width: 40%; pointer-events: none;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.65), transparent);
  animation: mv-glint 4.5s ease-in-out infinite; transform: translateX(-120%);
}
html.menus-v2 #nrg-meter-fill::after { animation-delay: 0.6s; }
html.menus-v2 #heat-meter-fill::after { animation-delay: 1.2s; }
html.menus-v2 .cr-meter-fill::after { animation-delay: 1.8s; }
@keyframes mv-glint { 0%, 60% { transform: translateX(-120%); } 100% { transform: translateX(260%); } }
html.menus-v2 .hud-vital-value { position: relative; }
html.menus-v2 .hud-vital-value b { display: inline-block; }

/* A value that changed flashes; its delta floats off it. */
html.menus-v2 .mv-tick { animation: mv-tick 0.6s ease-out; }
@keyframes mv-tick { 0% { filter: brightness(2.2); transform: scale(1.35); text-shadow: 0 0 14px currentColor; } 100% { transform: none; } }
html.menus-v2 .mv-delta {
  position: absolute; right: 0; top: -2px; pointer-events: none; z-index: 6; white-space: nowrap;
  font: 700 11px 'Share Tech Mono', monospace; text-shadow: 0 0 8px currentColor;
  animation: mv-delta 1.2s cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
}
html.menus-v2 .mv-delta.up { color: #37f5a3; }
html.menus-v2 .mv-delta.down { color: #ff5c8a; }
@keyframes mv-delta { 0% { opacity: 0; transform: translateY(4px) scale(0.8); } 15% { opacity: 1; transform: translateY(-4px) scale(1.15); }
  100% { opacity: 0; transform: translateY(-22px); } }

/* ---- Programs ---- */
html.menus-v2 .sw-mod { --tile: var(--mv-cyan); border-radius: 3px; transition: border-color 0.2s, box-shadow 0.25s, background-color 0.25s, transform 0.2s; }
html.menus-v2 .sw-mod:hover { transform: translateX(3px); box-shadow: 0 0 14px rgba(0, 255, 245, 0.2); }
html.menus-v2 .sw-mod.on { --tile: var(--mv-green); animation: mv-load-flash 0.7s ease-out; }
@keyframes mv-load-flash { 30% { box-shadow: 0 0 28px rgba(77, 255, 159, 0.7), inset 0 0 26px rgba(77, 255, 159, 0.3); } }
/* The load sweep: a band crosses the card when it becomes resident. */
html.menus-v2 .sw-mod.on .mv-sweep { animation: mv-sweep 0.7s cubic-bezier(0.4, 0, 0.2, 1); }
html.menus-v2 .sw-mod .mv-trace { opacity: 0; }
html.menus-v2 .sw-mod .mv-trace::before, html.menus-v2 #toolbar-actions button.sh-tile-load-btn .mv-trace::before { animation-play-state: paused; }
html.menus-v2 .sw-mod:hover .mv-trace::before, html.menus-v2 .sw-mod.on .mv-trace::before,
html.menus-v2 #toolbar-actions button.sh-tile-load-btn:hover .mv-trace::before, html.menus-v2 #toolbar-actions button.sh-tile-load-btn.on .mv-trace::before { animation-play-state: running; }
html.menus-v2 .sw-mod:hover .mv-trace, html.menus-v2 .sw-mod.on .mv-trace { opacity: 0.8; }
html.menus-v2 .sw-mod-load-fill { transition: width 0.7s cubic-bezier(0.2, 0.8, 0.2, 1); }
html.menus-v2 .sw-mem-pip { transition: background-color 0.3s, box-shadow 0.3s; }

/* ---- Action tiles: the old colours; --tile is each one's own old accent, for the motion. ---- */
html.menus-v2 #toolbar-actions .act-group[data-group="navigate"] { --side: var(--mv-cyan); }
html.menus-v2 #toolbar-actions .act-group[data-group="recon"] { --side: var(--mv-green); }
html.menus-v2 #toolbar-actions .act-group[data-group="strike"] { --side: var(--mv-pink); }
html.menus-v2 #toolbar-actions .act-group-label { transition: letter-spacing 0.3s, text-shadow 0.3s; }
html.menus-v2 #toolbar-actions .act-group:has(button:hover:not(:disabled)) .act-group-label {
  letter-spacing: 0.34em; text-shadow: 0 0 12px currentColor;
}
/* The group rule keeps its old gradient and carries a running light. */
html.menus-v2 #toolbar-actions .act-group-rule { position: relative; overflow: hidden; }
html.menus-v2 #toolbar-actions .act-group-rule::after {
  content: ''; position: absolute; top: -1px; bottom: -1px; left: 0; width: 100%;
  background: linear-gradient(90deg, transparent 40%, var(--side) 46%, #fff 50%, var(--side) 54%, transparent 60%);
  animation: mv-rule 3.2s ease-in-out infinite; transform: translateX(-60%);
}
html.menus-v2 #toolbar-actions .act-group[data-group="recon"] .act-group-rule::after { animation-delay: 0.5s; }
html.menus-v2 #toolbar-actions .act-group[data-group="strike"] .act-group-rule::after { animation-delay: 1s; }
@keyframes mv-rule { 0% { transform: translateX(-60%); } 70%, 100% { transform: translateX(60%); } }

html.menus-v2 #toolbar-actions button.sh-tile-load-btn { --tile: var(--side); border-radius: 4px; transition: border-color 0.25s, box-shadow 0.3s, filter 0.25s, transform 0.12s; }
html.menus-v2 #toolbar-actions button#btn-safehouse { --tile: var(--mv-violet); }
html.menus-v2 #toolbar-actions button[data-act="capture"] { --tile: var(--mv-gold); }
html.menus-v2 #toolbar-actions button.sh-tile-load-btn .mv-trace { opacity: 0; animation-duration: 1.6s; }
html.menus-v2 #toolbar-actions button.sh-tile-load-btn:hover:not(:disabled) { filter: brightness(1.15); }
html.menus-v2 #toolbar-actions button.sh-tile-load-btn:hover:not(:disabled) .mv-trace { opacity: 1; }
html.menus-v2 #toolbar-actions button.sh-tile-load-btn:active:not(:disabled) { transform: scale(0.97); }
/* The hover sweep: one band of light across the face. */
html.menus-v2 .mv-sweep {
  position: absolute; inset: 0; pointer-events: none; z-index: 2; border-radius: inherit; overflow: hidden;
  background: linear-gradient(105deg, transparent 35%, color-mix(in srgb, var(--tile) 35%, transparent) 48%, rgba(255, 255, 255, 0.35) 50%, transparent 62%) no-repeat;
  background-size: 250% 100%; background-position: 130% 0; opacity: 0;
}
html.menus-v2 #toolbar-actions button.sh-tile-load-btn:hover:not(:disabled) .mv-sweep { animation: mv-sweep 0.75s cubic-bezier(0.4, 0, 0.2, 1); }
@keyframes mv-sweep { 0% { opacity: 1; background-position: 130% 0; } 100% { opacity: 1; background-position: -30% 0; } }
/* Armed: the frame light runs fast and the glow breathes. */
html.menus-v2 #toolbar-actions button.sh-tile-load-btn.on { animation: mv-armed 1.3s ease-in-out infinite; }
html.menus-v2 #toolbar-actions button.sh-tile-load-btn.on .mv-trace { opacity: 1; animation-duration: 0.9s; }
@keyframes mv-armed { 0%, 100% { box-shadow: 0 0 14px color-mix(in srgb, var(--tile) 35%, transparent); }
  50% { box-shadow: 0 0 34px color-mix(in srgb, var(--tile) 75%, transparent), inset 0 0 26px color-mix(in srgb, var(--tile) 30%, transparent); } }
html.menus-v2 #toolbar-actions .act-btn-icon { transition: transform 0.45s cubic-bezier(0.3, 1.6, 0.5, 1), box-shadow 0.3s; }
html.menus-v2 #toolbar-actions button:hover:not(:disabled) .act-btn-icon { transform: rotate(90deg) scale(1.12); box-shadow: 0 0 14px var(--tile); }
html.menus-v2 #toolbar-actions button:hover:not(:disabled) .act-btn-label { display: inline-block; animation: mv-glitch 0.4s steps(2) 1; }
@keyframes mv-glitch {
  0% { text-shadow: -2px 0 #ff5c8a, 2px 0 #45fff0; transform: translateX(-1px); }
  30% { text-shadow: 2px 0 #ff5c8a, -2px 0 #45fff0; transform: translateX(1px) skewX(-8deg); }
  60% { text-shadow: -1px 0 #ff5c8a, 1px 0 #45fff0; transform: none; }
}

/* Click: a ripple from the pointer. */
html.menus-v2 .mv-ripple {
  position: absolute; width: 10px; height: 10px; margin: -5px 0 0 -5px; border-radius: 50%; pointer-events: none; z-index: 4;
  border: 2px solid var(--tile, var(--mv-cyan)); box-shadow: 0 0 12px var(--tile, var(--mv-cyan));
  animation: mv-ripple 0.55s cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
}
@keyframes mv-ripple { to { transform: scale(26); opacity: 0; border-width: 0.3px; } }

/* ---- Entry: panels wipe in one after another, a bright edge leading. Runs once the page's own
   boot reveal has finished (menus-fx.js adds .mv-boot and the --mv-i order). ---- */
html.menus-v2.mv-boot .mv-in { animation: mv-in 0.55s cubic-bezier(0.2, 0.8, 0.2, 1) backwards; animation-delay: calc(var(--mv-i, 0) * 70ms); }
@keyframes mv-in {
  0% { clip-path: inset(0 100% 0 0); filter: brightness(2.2); }
  60% { filter: brightness(1.4); }
  100% { clip-path: inset(0 0 0 0); filter: none; }
}

/* ---- Packet feed ---- */
html.menus-v2 #feed-wrap { border-radius: 4px; }
html.menus-v2 .feed-filter { transition: color 0.2s, background-color 0.2s, border-color 0.2s; }
html.menus-v2 #feed > * { animation: mv-row 0.5s cubic-bezier(0.2, 0.8, 0.2, 1); }
@keyframes mv-row { 0% { opacity: 0; transform: translateX(-12px); background: rgba(0, 255, 245, 0.2); } 100% { background: transparent; } }

/* The old skin cuts its corners with clip-path, which would also cut the frame light and the glow. */
html.menus-v2 #stats, html.menus-v2 .programs-panel, html.menus-v2 .sw-mod,
html.menus-v2 #toolbar-actions button.sh-tile-load-btn, html.menus-v2 #toolbar-actions .act-btn-icon,
html.menus-v2 .bar-right .info-array button, html.menus-v2 #feed-wrap { clip-path: none; }

/* Tile widths (owner, 2026-10-08: "DEEP SCAN is oddly long"): a group's width follows how many
   tiles it shows, so every tile is the same width — DEEP SCAN alone in RECON no longer stretches
   over a third of the bar. STRIKE's two (CAPTURE, RAID — the actions the game is about) are a
   quarter wider. The demo hides SAFEHOUSE with CSS, not [hidden], so there CORE counts as one.
   The phone and narrow (wrapping) layouts keep their own sizing. */
@media (min-width: 901px) {
  html.menus-v2:not([data-phone="land"]):not([data-phone="port"]) #toolbar-actions .act-group[data-group="navigate"] { flex-grow: 1; }
  html.menus-v2:not([data-phone="land"]):not([data-phone="port"]) body:not(.mode-demo) #toolbar-actions .act-group[data-group="navigate"]:has(button:not([hidden]):not(.cl-locked) ~ button:not([hidden]):not(.cl-locked)) { flex-grow: 2; }
  html.menus-v2:not([data-phone="land"]):not([data-phone="port"]) #toolbar-actions .act-group[data-group="recon"] { flex-grow: 1; }
  html.menus-v2:not([data-phone="land"]):not([data-phone="port"]) #toolbar-actions .act-group[data-group="recon"]:has(button:not([hidden]) ~ button:not([hidden])) { flex-grow: 2; }
  html.menus-v2:not([data-phone="land"]):not([data-phone="port"]) #toolbar-actions .act-group[data-group="strike"] { flex-grow: 1.25; }
  html.menus-v2:not([data-phone="land"]):not([data-phone="port"]) #toolbar-actions .act-group[data-group="strike"]:has(button:not([hidden]):not(.cl-locked) ~ button:not([hidden]):not(.cl-locked)) { flex-grow: 2.5; }
}

/* Clearance gates (world/teach.js applyClearanceGates): a tile is out of the bar until its
   clearance; when it opens it wipes in with a bright edge, then glows with a NEW tag until it is
   first clicked. */
html.menus-v2 #toolbar-actions button.sh-tile-load-btn.cl-locked { display: none !important; }
html.menus-v2 #toolbar-actions button.sh-tile-load-btn.cl-unlocking { animation: cl-unlock 1.4s cubic-bezier(0.2, 0.8, 0.2, 1) both; }
@keyframes cl-unlock {
  0% { clip-path: inset(0 100% 0 0); filter: brightness(3); }
  45% { clip-path: inset(0 0 0 0); filter: brightness(2); }
  100% { clip-path: inset(0 0 0 0); filter: none; }
}
html.menus-v2 #toolbar-actions button.sh-tile-load-btn.cl-new:not(.cl-unlocking) { animation: cl-new-glow 1.8s ease-in-out infinite; }
@keyframes cl-new-glow { 50% { box-shadow: 0 0 30px color-mix(in srgb, var(--tile) 75%, transparent), inset 0 0 22px color-mix(in srgb, var(--tile) 30%, transparent); } }
html.menus-v2 .cl-new-tag {
  position: absolute; top: 4px; right: 4px; z-index: 5; pointer-events: none;
  padding: 1px 5px; font: 700 8px 'Share Tech Mono', monospace; letter-spacing: 0.14em;
  color: #04110f; background: var(--tile, #00fff5); box-shadow: 0 0 10px var(--tile, #00fff5);
  animation: cl-tag 1s steps(2) infinite;
}
@keyframes cl-tag { 50% { opacity: 0.55; } }

/* ---- Cinema mode for trailer footage (docs/TRAILER_PLAN.md, world/cinema.js) ----
   ?cinema: the clean map — every menu, banner, toast and the cursor gone, the map edge to edge.
   ?cinema=hud: the menus stay (for shots of the interface and the duel); only debug marks and the
   guest's first choice (PLAY TRAINING / REGISTER) go. */
html.cinema #debug-reveal-badge, html.cinema #build-id, html.cinema #playtest-rec,
html.cinema #fs-btn, html.cinema #a2hs-hint, html.cinema #btn-app, html.cinema #demo-cta-banner { display: none !important; }
html.cinema-clean #bar, html.cinema-clean #toolbar, html.cinema-clean #hud, html.cinema-clean #hud-tab,
html.cinema-clean #inspect-dock, html.cinema-clean #map-style, html.cinema-clean #map-zoom,
html.cinema-clean #deploy-banner, html.cinema-clean #demo-cta-banner, html.cinema-clean #demo-mission,
html.cinema-clean #demo-conversion, html.cinema-clean #frontier-chips, html.cinema-clean #deploy-pending,
html.cinema-clean #deploy-toast, html.cinema-clean #loot-toast-stack, html.cinema-clean #nd-toast,
html.cinema-clean #phone-peeks, html.cinema-clean #bulletin, html.cinema-clean #clearance-beat,
html.cinema-clean #holding-teach, html.cinema-clean #softlock-modal, html.cinema-clean #ram-release-teach,
html.cinema-clean #node-deploy-overlay, html.cinema-clean #neural-link, html.cinema-clean .mv-beam { display: none !important; }
html.cinema-clean body { padding: 0; }
html.cinema-clean #panel { width: 100%; max-width: none; height: 100dvh; max-height: none; border: 0; box-shadow: none; }
html.cinema-clean, html.cinema-clean * { cursor: none !important; }
/* L: letterbox to 2.39:1. */
#cinema-letterbox { display: none; }
html.cinema-letterbox #cinema-letterbox { display: block; position: fixed; inset: 0; z-index: 2147483000; pointer-events: none; }
#cinema-letterbox i { position: absolute; left: 0; right: 0; height: max(0px, calc((100vh - 100vw / 2.39) / 2)); background: #000; }
#cinema-letterbox i:first-child { top: 0; }
#cinema-letterbox i:last-child { bottom: 0; }
/* V: a 9:16 guide for framing the vertical cut — the outside dimmed. */
#cinema-vertical { display: none; }
html.cinema-vertical #cinema-vertical {
  display: block; position: fixed; top: 0; bottom: 0; left: 50%; width: calc(100vh * 9 / 16); transform: translateX(-50%);
  z-index: 2147483000; pointer-events: none; outline: 1px dashed rgba(255, 255, 255, 0.5); box-shadow: 0 0 0 100vmax rgba(0, 0, 0, 0.55);
}
/* H: the key hint (hidden on the first shot). */
#cinema-hint {
  display: none; position: fixed; left: 50%; bottom: 14px; transform: translateX(-50%); z-index: 2147483001; pointer-events: none;
  padding: 6px 12px; font: 11px 'Share Tech Mono', monospace; letter-spacing: 0.06em; color: #d7f4f6;
  background: rgba(5, 8, 13, 0.9); border: 1px solid rgba(0, 255, 245, 0.45); white-space: nowrap;
}
#cinema-hint.show { display: block; }
#cinema-hint b { color: #00fff5; margin-right: 8px; letter-spacing: 0.2em; }
