Commit Graph
837 Commits
Author SHA1 Message Date
digital-garbage ebc8a121a8 Report chain sampler step progress in Movie Editor UI
Wire ProgressBar callbacks through scene-chain _sample_chunk so denoise
steps update the global progress hook the frontend polls. Reset progress
when a new generation is queued; label the readout as sampling N/M.
2026-06-10 14:30:46 +03:00
digital-garbage 7dc6b22d65 Movie Editor: keep scene audio clips within video clip width
Audio blocks were growing past their scene duration because flex
content and min-width: 48px overrode the inline width. Match video
clip sizing, cap max-width, and let the volume slider shrink inside.
2026-06-10 14:26:36 +03:00
digital-garbage b05fafff15 Movie Editor: reorganize engine settings into Studio/Chain cards
Split Project settings into Output, Prompt, and Engine bands with
collapsible FunPack Studio and Chain Sampler cards. Group chain knobs
by timing, continuity, guidance, decode, and experimental; add
transition_duration, use_same_seed, and decode_tile_size. Show engine
context strip in scene view, non-default badges, and locked carry hint
for multi-scene runs.
2026-06-10 14:19:35 +03:00
digital-garbage 9884bb0f0e Movie Editor: add Video and Audio lane labels on timeline gutter
Replace the old audio-only "Clips" gutter with a shared sticky left column
that labels the video track and each audio lane without offsetting clip
positions — video and audio still share the same time origin.
2026-06-10 14:10:11 +03:00
digital-garbage 3a7b89ba2b Movie Editor: clear scene rating when a scene is regenerated
Reset rating to empty after a successful generate so the timeline shows
"— rate —" and Studio receives "-Just forget it-" until the user rates again.
2026-06-10 14:05:50 +03:00
digital-garbage 82bb1511d5 Movie Editor: align audio clips with video on the timeline
Remove the left "Clips" lane label gutter that offset audio blocks by 72px
so per-scene and inserted audio share the same time origin as video clips.
2026-06-10 14:04:07 +03:00
digital-garbage da3f06199d Merge branch 'main' into dev — sync README updates from main 2026-06-10 14:00:10 +03:00
DigitalGarbage 405c4ea0b6 Update README.md 2026-06-10 13:59:51 +03:00
DigitalGarbage 2738a6c285 Update README.md 2026-06-10 13:59:51 +03:00
DigitalGarbage 2ccc20a832 Update README.md 2026-06-10 13:59:51 +03:00
DigitalGarbage 9e44a8dc1a Update README.md 2026-06-10 13:59:51 +03:00
DigitalGarbage b3cd11c0a0 Update README.md 2026-06-10 13:59:51 +03:00
digital-garbage 22aef8de03 Movie Editor: dock panel tabs + timeline audio lanes
Add Media/Preview/Settings toggles above the timeline that preserve the
canonical layout when all three are on and collapse panels intelligently
when toggled off. Move per-clip volume and inserted audio tracks from the
inspector onto NLE-style lanes below the video track.
2026-06-10 13:58:50 +03:00
DigitalGarbage 9308f3a945 Update README.md 2026-06-10 01:00:54 +03:00
DigitalGarbage 4ffc21d831 Update README.md 2026-06-10 00:59:43 +03:00
DigitalGarbage de8104dd79 Update README.md 2026-06-10 00:51:19 +03:00
DigitalGarbage cee3355b24 Update README.md 2026-06-10 00:44:03 +03:00
DigitalGarbage 1f4c9f6e68 Update README.md 2026-06-10 00:35:41 +03:00
digital-garbageandClaude Opus 4.8 44447baa40 Movie Editor: don't rebuild the editor on generation progress ticks
A long generation polled progress every ~700ms via set()->notify(), rebuilding the whole
editor (inspector/timeline/player) each time — so saving rendered frames to the bin or
adding effects got interrupted constantly. Progress ticks now use updateGenProgress(),
which mutates state.gen quietly and fires a 'funpack-gen-progress' DOM event; the player
updates the readout/progress bar in place. Full notify() is reserved for state transitions
(queued/done/error), so the editor stays interactive throughout a run.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 01:39:53 +03:00
digital-garbageandClaude Opus 4.8 330cb1a9e4 Movie Editor: disable built-in pipeline + global video/audio outputs
- Models: 'Disable built-in pipeline' toggle (config.disable_core). When off, the build
  skips the entire fixed FunPack core graph and runs only user-wired nodes.
- Global editor outputs: wire any slot's IMAGE output to 'global:video' and AUDIO to
  'global:audio' (shown at the top of the wire-target list). The builder synthesizes a
  VHS_VideoCombine on demand that muxes the wired frames WITH the wired audio into one
  video+audio file, which the editor previews from history. Works with core on or off.
- Guards: skip core producers/targets that don't exist when core is disabled; non-blocking
  warning if nothing is wired to the global video output with core off. _project_models
  recognizes a project whose only config is disable_core.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 01:32:27 +03:00
digital-garbageandClaude Opus 4.8 c47bcfc71b Movie Editor: fix preview freeze from audio-volume assignment
A non-finite video.volume throws on assignment; since _applyFx runs every rAF tick, that
threw inside the tick and froze playback. Volume is now sanitized (finite, clamped) and
the assignment is try-guarded, and the tick's _applyFx call is wrapped so no effect error
can ever stop the playback loop.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 01:11:49 +03:00
digital-garbageandClaude Opus 4.8 54d58a1e6b Movie Editor: audio editing — per-clip volume, inserted tracks, original toggle
- Per-clip original audio gain (Scene.audio_volume; inspector slider, 0 mutes). Applied at
  render (volume filter) and in the live preview (video.volume, clamped 0..1).
- Project-level audio mix: keep_original_audio toggle (drop the generated LTXAV audio) and
  audio_tracks[] — inserted background tracks from the Media bin, each with start offset +
  volume. Mixed at render via adelay + amix(normalize=0), trimmed to the montage length.
- All four cases work: lower/boost a clip, add one or many tracks, keep original + tracks,
  original-only, tracks-only, or fully silent (no audio stream mapped).
- Render route resolves track media to files (media.path_for), appends them as inputs after
  the clips, and maps [aout] only when there's audio. renderFinal flushes the project save
  first (tracks/toggle live on the project, read from disk at render).
- Inspector: per-scene Clip audio + Project Audio section (toggle, track cards, add-from-bin).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 01:03:44 +03:00
digital-garbageandClaude Opus 4.8 aeded5cafa Movie Editor: fix render — normalize canvas + virtual zoom (zoompan)
Render failed two ways: clips with different native sizes (768x768 vs 576x768) broke
xfade (needs matching size/fps/sar), and zoom physically rescaled the frame.

- Every clip is now normalized to one canvas (scale+pad to clips[0] size, fixed fps,
  setsar=1) before effects, so xfade/concat always match.
- Zoom is virtual via zoompan: output stays fixed at canvas size, only the content scales
  within it (in 1.0->1.2, out 1.2->1.0). No frame-size change -> renders cleanly.
- Preview matches (zoom-out now pulls back 1.2->1.0); labels updated (push / pull back).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 00:44:36 +03:00
digital-garbageandClaude Opus 4.8 6eab8d9632 Movie Editor: Effects dropdown on the timeline toolbar
'✨ Effects ▾' on the selected clip: pick an effect/transition (zoom in/out, blur, fade
in/out, crossfade/fade-to-black/wipe → next), enter its value (strength/seconds/frames)
where relevant, and Add. Writes onto the scene, so the inspector's per-scene controls
remain the single source of truth and reflect whatever is added here.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 00:39:54 +03:00
digital-garbageandClaude Opus 4.8 4e9d0e4c1d Movie Editor: Play from end-of-timeline restarts from the beginning
If the playhead is at/past the end (or on no clip) when Play is pressed, reset it to 0 and
play from the top instead of doing nothing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 00:31:37 +03:00
digital-garbageandClaude Opus 4.8 8119ba2809 Movie Editor: drag-drop clip reordering on the timeline
Grab a clip body and drag left/right to reorder; an amber insertion line shows the drop
spot, and rebuilds are hard-blocked mid-drag so the dragged clip doesn't vanish. A 5px
threshold keeps plain clicks as select; trim handle and action buttons opt out. store
gains moveSceneTo(id, index). The tiny ‹/› move buttons stay as a fallback.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 00:31:11 +03:00
digital-garbageandClaude Opus 4.8 4da41f3333 Movie Editor: per-scene video effects + seam transitions (render + live preview)
Post-decode pixel ops (never re-encode to latent):
- Per-scene effects: gaussian blur, fade in/out, Ken-Burns zoom in (crop) / out (pad).
  Stored in Scene.effects {blur, fade_in, fade_out, zoom}.
- Seam video transitions: crossfade/dissolve, fade-through-black, wipe L/R via
  Scene.video_transition + transition_frames (length). Crossfade overlaps the clips
  (xfade + audio acrossfade) so the montage shortens by the transition length.
- Render route builds a filter_complex (_build_render_filter): per-clip effect chain via
  scale eval=frame + crop/pad/gblur/fade, then a left-fold of xfade/concat seams.
- Live preview approximates per-clip fx (CSS blur/scale/opacity, playhead-synced so it
  tracks scrubbing); crossfades preview as hard cuts but render correctly.
- Inspector exposes all of it per scene.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 00:28:41 +03:00
digital-garbageandClaude Opus 4.8 6433c87881 Movie Editor: fix dead transport buttons during playback
The playhead listener called _renderTransport on every rAF tick, clearing and recreating
the play/pause/stop buttons ~60x/sec. A click's mousedown/mouseup straddled a rebuild, so
the button was destroyed mid-click and no click fired. Playhead ticks now update only the
timecode text and play-button glyph in place; full rebuilds happen only on discrete
transport actions and store changes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 00:12:22 +03:00
digital-garbageandClaude Opus 4.8 352ed35ef9 Movie Editor: capture frame to Media bin when no scene chosen
The transport frame capture no longer requires a scene: with the selector left on
'— save to Media bin —' it just saves the frame as an asset (usable as an anchor later
via drag/pick); pick a scene to apply it as that scene's i2v anchor. Button label
adapts (Save frame / Use as anchor).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 20:57:16 +03:00
digital-garbageandClaude Opus 4.8 29b7797c80 Movie Editor: timestamp export/render filenames for uniqueness
Scene export -> <project>_sceneN_YYYYMMDD-HHMMSS.mp4; final render ->
<project>_final_YYYYMMDD-HHMMSS.mp4, so repeated saves never collide.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 19:18:00 +03:00
digital-garbageandClaude Opus 4.8 cac5b07e39 Movie Editor: only inject scene separators for multi-scene runs
Single-scene runs are one segment already, so no 'scene N' marker is injected (avoids
leaking it into the prompt). Multi-scene runs inject before every scene lacking a leading
trigger (incl. the first, which Studio would otherwise fold into the anchor).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 19:16:38 +03:00
digital-garbageandClaude Opus 4.8 77bf2f8439 Movie Editor: fix multi-scene runs + anchor/export/fallback + studio toggles
- #1 Multi-scene run only generated scene 1: a carry scene has no leading transition so
  Studio merged it. Generation prompt now injects a separator before any scene lacking a
  leading trigger (transition_to_next or generic 'scene N') so Studio splits into exactly
  one conditioning per scene. Display/global prompt stays verbatim (for_generation flag).
- #2 'Use as anchor' no longer defaults to scene 1 — requires picking a scene, so it can't
  silently overwrite an existing image. Anchor capture drops the obsolete target.
- #3 Export uses unique names: <project>_sceneN.mp4.
- #4 A scene whose image was deleted falls back to carry (i2v guides) in run splitting.
- #5 Timeline/inspector edit-guard could stick (focused control removed w/o focusout),
  freezing refresh. Guards now self-clear when focus is actually gone.
- #6 Expose Studio refiner toggles (vision conditioning, reference injection, prompt
  repair) in the inspector -> studio_settings.refiner.
- #7 Embed-guidance mode (relative/absolute) now selectable (sampler combo knob).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 19:15:46 +03:00
digital-garbageandClaude Opus 4.8 7ffee3e688 Movie Editor: per-clip in/out model — splits & deletes honored in preview + render
Replace whole-run renderedSegments with per-scene sceneRenders {media, inSec}. The
player builds per-scene clips (media, startSec, durationSec, inSec) and plays each clip's
[inSec, inSec+dur] window via a rAF tick (precise out-points, so deleted parts aren't
played; contiguous split seams continue seamlessly). Split sets the second half's inSec;
delete drops the mapping. Render route takes per-clip in/dur and concatenates only kept
clips (ffmpeg -ss/-t + concat filter, audio preserved). Export/hasRender use sceneRenders.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 19:08:49 +03:00
digital-garbageandClaude Opus 4.8 b8fa482512 Movie Editor: don't pop boot overlay on video load errors; keep render across split
- Boot-error overlay ignored resource-load errors: a pooled <video> failing to fetch
  fired a capture-phase 'error' with empty message -> scary 'load error' banner. Now
  skip events targeting an element (resource errors); only real script errors show.
- Split now assigns the new half a client id and adds it to the rendered segment's
  sceneIds, so the existing video spans BOTH halves (one source, like a real NLE) and
  the monitor keeps playing across the cut instead of going blank.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 14:52:32 +03:00
digital-garbageandClaude Opus 4.8 c39af077ab Movie Editor: make Reset Studio session a toggle (disarmable)
Clicking 'Reset Studio session' again now cancels a pending reset (mis-click safe);
the menu shows 'armed — click to cancel' when set.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 14:47:53 +03:00
digital-garbageandClaude Opus 4.8 8ce0a24c40 Movie Editor: fix log panel not closing
.log-panel had display:flex, which overrode the [hidden] attribute's display:none, so
the close/toggle never hid it. Add .log-panel[hidden] { display:none }.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 14:46:14 +03:00
digital-garbageandClaude Opus 4.8 a7b553ca54 Movie Editor: inject scene image without a target; closable boot-error overlay
- _prepare_media no longer requires a per-scene 'target' (removed earlier) — it now
  injects the scene image as a LoadImage from just the asset ref. Fixes 'ImageTransformKJ
  .image (IMAGE): no node outputs IMAGE' for image-anchored scenes/runs: the image is
  now materialised and auto-wires to IMAGE inputs.
- Boot-error overlay gets a ✕ dismiss button so it can't permanently block the top menu
  (so you can still reach Restart ComfyUI etc.).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 14:41:06 +03:00
digital-garbageandClaude Opus 4.8 3ab367fb51 Movie Editor: ComfyUI backend log viewer
Add a 'Log' button in the menubar (next to Saved) that opens a collapsible panel
streaming ComfyUI's real backend log. The bridge tees stdout/stderr into a ring buffer
(writes still pass through to the terminal; captures print + logging); /api/log returns
the tail. Panel polls every 1.5s while open, auto-scrolls (pauses if you scroll up),
with Copy. Far more informative than our wrapped error messages.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 14:39:23 +03:00
digital-garbageandClaude Opus 4.8 50ef7edc57 Movie Editor: Reset Studio session button; don't auto-assign ratings; fix rating dropdown
- FunPack menu 'Reset Studio session' arms reset_session for the FIRST run of the next
  generation (false for the rest); shows ✓ armed. reset_session lives in
  studio_settings.refiner, set explicitly per run by the builder.
- Unrated scenes now send '-Just forget it-' to Studio instead of its default learning
  rating, so the system never learns from a rating the user didn't give (esp. after a
  reset / first generation).
- Timeline no longer rebuilds while a control (rating/transition dropdown, trim input)
  is focused, so autosave/progress notifies can't close the rating dropdown mid-pick;
  it re-syncs on blur.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 14:33:33 +03:00
digital-garbageandClaude Opus 4.8 9f6a6d3ba1 Movie Editor: fix per-scene split — set split_by_transitions in studio_settings
CRITICAL: split_by_transitions is NOT a top-level FunPackStudio input; Studio reads it
from studio_settings.refiner.split_by_transitions (default False). The builder set it
as a top-level input, which ComfyUI silently dropped (not in INPUT_TYPES) — so Studio
ran in single-scene mode and every scene got the whole prompt (scene 2's action bled
into scene 1). Now force split_by_transitions=True INSIDE the studio_settings JSON
(after user overrides), so Studio actually splits the combined prompt per scene.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 14:26:36 +03:00
digital-garbageandClaude Opus 4.8 c38ba2c09e Movie Editor: per-scene Studio rating + wire outputs into widget inputs
Rating:
- Scene.rating (V2_RATING_LABELS); /api/rating-labels exposes the options.
- Timeline toolbar 'Scene N ★' dropdown, shown ONLY when FunPack Studio is the
  conditioning provider AND the selected clip has a render. Rates that clip's own
  scene (cut-aware by scene id).
- Generation injects the run's rating into Studio (studio_inputs.rating) so Studio
  refines the next generation from it; empty = use Studio's default.

Wiring:
- Widget inputs (INT/FLOAT/STRING/BOOLEAN, e.g. EmptyLatentVideo.width/height) are
  now offered as manual wire destinations (ComfyUI converts a widget to an input when
  wired) — so ImageTransform's width/height outputs can drive them. They're still not
  auto-wired, so widget values aren't clobbered unless wired explicitly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 14:22:29 +03:00
digital-garbageandClaude Opus 4.8 77b4084a81 Movie Editor: progress hook accepts ComfyUI's extra kwargs (node_id)
ComfyUI calls PROGRESS_BAR_HOOK with extra args (e.g. node_id), which broke our chained
hook -> VHS_VideoCombine errored. Accept *args/**kwargs and forward them to the previous
hook (falling back to the 3-arg form if it can't take them).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 14:13:31 +03:00
digital-garbageandClaude Opus 4.8 f1c33b81ad Movie Editor: resolve V3 dynamic-combo options to their key value
COMFY_DYNAMICCOMBO_V3 options are dicts {key, inputs}, not strings — we were using the
whole object as the value (showing '[object Object]' and feeding ImageTransformKJ an
object). Normalise combo choices/defaults to the selectable key string everywhere
(_combo_choices/_combo_default), and coerce any stale '[object Object]'/dict slot value
back to the default at build. Combos now show real options and emit valid values.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 14:10:37 +03:00
digital-garbageandClaude Opus 4.8 5079ee7cd2 Movie Editor: seamless scrubbing via preloaded video pool (no black on cuts)
Replaced the single <video> (which reloaded src per clip -> black flash crossing a
cut) with a pool of preloaded <video>, one per clip file, in a persistent stage; only
the active clip is shown. Scrubbing/playing across cut boundaries swaps which video is
visible — already loaded, so the frame appears immediately. The pool is rebuilt as the
timeline changes (cuts/regens) and segment positions recompute live; _currentSeg is
refreshed each render so edits stay in sync.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 14:05:45 +03:00
digital-garbageandClaude Opus 4.8 e4544d2779 Movie Editor: step progress + Interrupt; treat V3 dynamic combos as widgets
- Generation progress: chain ComfyUI's global ProgressBar hook (no clobber) to record
  sampler current/total steps; /api/progress exposes it; the store polls it ~700ms and
  shows 'step X/Y' + a progress bar in the program monitor.
- Interrupt button (player overlay) -> /api/interrupt -> ComfyUI /interrupt; the run
  loop stops and shows 'Interrupted.'
- Fix ImageTransform (V3) blocking: keep_proportion/extra_padding/invert_crop are
  COMFY_DYNAMICCOMBO_V3 dropdown widgets, not sockets. Recognize any 'COMBO'-containing
  type as a widget across connection_inputs / widget_inputs / ports / widget defaults,
  so they're configured as combos and never reported as missing connections.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 13:59:52 +03:00
digital-garbageandClaude Opus 4.8 9a79c29f46 Movie Editor: click empty timeline to clear scene selection
Clicking the timeline background (not a clip, seam, or the ruler) now deselects the
current scene, switching the inspector back to Project view.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 13:54:43 +03:00
digital-garbageandClaude Opus 4.8 14df70a191 Movie Editor: play the whole sequence, not just one clip
The program monitor stalled after the first segment: on segment-end (and on play) it
called video.play() immediately after setting a new src + load(), so the play promise
rejected (media not ready) and the chain stopped — looking like it only plays the one
(highlighted) scene. Added a _playPending flag: when loading a different file, playback
starts on loadedmetadata; same-file seeks play immediately; pause cancels pending
autoplay. Segments now play through seamlessly, skipping ungenerated gaps.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 13:51:55 +03:00
digital-garbageandClaude Opus 4.8 02c89beef7 Movie Editor: drop redundant per-scene 'Feeds node input' target
Routing is owned by Models/nodes now (the scene image is an auto-wiring IMAGE
producer; a node can pull it via Input source = Timeline). The per-scene target was
a confusing second place to wire the same thing. Removed it from the image and
generated-frame sources; the scene just supplies the anchor image and the pipeline
routes it (default → Studio source image). Existing explicit targets still honored.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 13:28:02 +03:00
digital-garbageandClaude Opus 4.8 1214029f1c Movie Editor: scene/timeline image counts as an IMAGE source
A node's IMAGE input (e.g. ImageTransform) reported 'no node outputs IMAGE' because
the scene image comes from the timeline (injected as a LoadImage), not a node output.
Now the builder always materialises the scene image as media_load and registers it as
an IMAGE producer, so unwired IMAGE inputs auto-wire to the scene image. The Models
modal no longer flags required IMAGE inputs (the timeline can always feed them).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 13:24:38 +03:00
digital-garbageandClaude Opus 4.8 15a4fbf7d7 Movie Editor: preserve scroll, stop per-second autosave (save on blur instead)
- Inspector preserves scrollTop across rebuilds, so editing no longer jumps the panel
  to the top.
- Autosave only persists to disk; it doesn't need to fire every keystroke. Free-text/
  number fields now debounce 6s and are FLUSHED on blur (flushSave); discrete actions
  save ~1.2s after the last change. generate()/generateMontage() flush first so the
  server has the latest edits before reading the project.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 13:22:02 +03:00