/* ============================================================================
 * zen/core/core.css
 * ----------------------------------------------------------------------------
 * Design tokens + layout primitives + universal state classes.
 *
 * Load order (in a module's index.html):
 *   <link rel="stylesheet" href="../../zen/core/core.css">           ← tokens + primitives + states
 *   <link rel="stylesheet" href="../../zen/components/box/box.css">  ← component styles
 *   <link rel="stylesheet" href="style.css">                         ← module overrides
 *
 * Contains:
 *   - CSS custom properties (design tokens)
 *   - Global reset + body background
 *   - Scene + world + canvas primitives (.z-scene / .z-world / .z-canvas)
 *   - Universal state classes (.a-active / .a-past / .a-dimmed)
 *   - Layout framework CSS (.zen-scope / .zen-scope-label)
 *   - HUD primitives (.z-hud-title / .z-hud-sub / .z-hud-step / .z-progress)
 *
 * All legacy aliases (`.o-scene`, `.o-world`, `.o-canvas`, `.ob-scope`, etc.)
 * live in `zen/compat.js`-adjacent `zen/compat.css` or inline here via
 * attribute selectors, so that transitional modules that mix old and new
 * class names keep rendering.
 * ============================================================================ */

/* ===== Reset ============================================================== */
* { margin: 0; padding: 0; box-sizing: border-box; }

/* ===== Design tokens ====================================================== */
:root {
    /* Backgrounds */
    --bg:       #0D1117;
    --bg2:      #161B22;
    --bg3:      #1C2128;
    /* Role palette */
    --green:    #00E676;
    --violet:   #7C3AED;
    --blue:     #3B82F6;
    --orange:   #F97316;
    --red:      #EF4444;
    --yellow:   #FBBF24;
    --cyan:     #22D3EE;
    --pink:     #F472B6;
    --teleport: #512FC9;
    /* Neutrals */
    --white:    #FFFFFF;
    --gray:     #9CA3AF;
    --border:   #374151;
    /* Aliases (legacy) */
    --text:     #FFFFFF;
    --panel:    #161B22;
    --panel2:   #1C2128;
    /* Motion */
    --ease-natural: cubic-bezier(.16, 1, .3, 1);
    --ease-camera:  cubic-bezier(0.4, 0, 0.2, 1);
    --d-fast:   0.35s;
    --d-med:    0.6s;
    --d-slow:   0.8s;
    --d-camera: 1.2s;
    /* Radii */
    --r-sm: 6px;
    --r-md: 10px;
    --r-lg: 14px;
    --r-xl: 20px;
}

/* ===== Body =============================================================== */
/* `height: 100dvh` = dynamic viewport — tracks iOS Safari's address-bar
 * show/hide correctly (100vh would lock to the largest possible viewport
 * height, which breaks letterbox math once the bar appears). */
html, body { height: 100dvh; min-height: 100%; }
body {
    font-family: 'Segoe UI', system-ui, sans-serif;
    background: var(--bg);
    color: var(--white);
    overflow: hidden;
    overscroll-behavior: none;   /* kill iOS rubber-banding */
}
body::before {
    content: '';
    position: fixed; inset: 0;
    background-image: radial-gradient(circle, rgba(255,255,255,0.025) 1px, transparent 1px);
    background-size: 32px 32px;
    pointer-events: none; z-index: -1;
}

/* ===== Scene / world / canvas (layout primitives) =========================
 * The scene is LOCKED to a virtual 1920×1080 frame. Regardless of the actual
 * viewport, every module authors its content against this fixed coordinate
 * system — `data-at` percentages resolve to pixels of 1920×1080, canvas buffer
 * dims are 1920×1080, Bézier anchors are stable across devices.
 *
 * Fitting to the real viewport is done via a single CSS var `--z-fit`, set by
 * `zen.fit()` (see engine.js) on init / resize / orientationchange. The scene
 * stays centered and the surplus device real-estate becomes black letterbox
 * bars (body background already dark).
 *
 * On a 16:9 laptop or 4K vidéoproj : `--z-fit` = viewport_w / 1920, no bars.
 * On an iPad landscape (4:3)       : `--z-fit` = viewport_h / 1080, h-bars.
 * On an iPhone portrait            : `--z-fit` = viewport_w / 1920, v-bars.
 *
 * Side-effect: the HUD bar (position:fixed, top:0 of viewport) now sits on
 * the top letterbox band on non-16:9 devices — which happens to be the
 * right place for navigational chrome. */
.z-scene, .o-scene {
    position: fixed;
    top: 50%; left: 50%;
    width: 1920px; height: 1080px;
    transform-origin: center center;
    transform: translate(-50%, -50%) scale(var(--z-fit, 1));
    overflow: hidden;
}
.z-world, .o-world {
    position: absolute; top: 0; left: 0;
    width: 100%; height: 100%;
    transform-origin: 0 0;
    transition: transform var(--d-camera) var(--ease-camera);
    will-change: transform;
}
.z-canvas, .o-canvas {
    position: absolute; top: 0; left: 0;
    width: 100%; height: 100%;
    pointer-events: none;
    z-index: 1;
}

/* ===== Universal state classes ============================================ *
 * Three mutually-exclusive classes. `.a-active` and `.a-past` must never
 * coexist — use zen.state.set(el, …) to enforce the invariant.             */

/* Default (no state class) = dim, pre-introduction look.
 * Components declare their own base opacity/appearance; core.css only sets
 * the shared "on" / "past" / "dimmed" modifiers that component CSS reads. */

/* Binary visibility for tokens / labels / badges: add `.show` to reveal. */
.show { /* anchor for transition targets; individual components scope it */ }

/* ===== Layout framework (zen-scope + ob-scope alias) ====================== */
.zen-scope, .ob-scope {
    position: absolute;
    box-sizing: border-box;
    border: 2px dashed rgba(255, 255, 255, 0.15);
    border-radius: var(--r-xl);
    background: linear-gradient(145deg, rgba(255,255,255,0.015), rgba(255,255,255,0.005));
    z-index: 1;
    transition: border-color var(--d-slow) var(--ease-natural),
                box-shadow   var(--d-slow) var(--ease-natural),
                opacity      var(--d-slow) var(--ease-natural);
    opacity: 0.35;
}
.zen-scope.a-active, .ob-scope.a-active { opacity: 1; }

/* Role coloring for scopes */
.zen-scope.a-agent, .ob-scope.a-agent            { border-color: rgba(249,115,22,0.35); }
.zen-scope.a-agent.a-active, .ob-scope.a-agent.a-active
                                                 { border-color: rgba(249,115,22,0.85); box-shadow: 0 0 40px rgba(249,115,22,0.15); }
.zen-scope.a-proxy, .ob-scope.a-proxy            { border-color: rgba(34,211,238,0.35); }
.zen-scope.a-proxy.a-active, .ob-scope.a-proxy.a-active
                                                 { border-color: rgba(34,211,238,0.85); box-shadow: 0 0 40px rgba(34,211,238,0.15); }
.zen-scope.a-auth, .ob-scope.a-auth              { border-color: rgba(0,230,118,0.35); }
.zen-scope.a-auth.a-active, .ob-scope.a-auth.a-active
                                                 { border-color: rgba(0,230,118,0.85);  box-shadow: 0 0 40px rgba(0,230,118,0.15); }
.zen-scope.a-idp, .ob-scope.a-idp                { border-color: rgba(124,58,237,0.35); }
.zen-scope.a-idp.a-active, .ob-scope.a-idp.a-active
                                                 { border-color: rgba(124,58,237,0.85); box-shadow: 0 0 40px rgba(124,58,237,0.15); }
.zen-scope.a-wds, .ob-scope.a-wds                { border-color: rgba(59,130,246,0.35); }
.zen-scope.a-wds.a-active, .ob-scope.a-wds.a-active
                                                 { border-color: rgba(59,130,246,0.85); box-shadow: 0 0 40px rgba(59,130,246,0.15); }
.zen-scope.a-dc,  .ob-scope.a-dc                 { border-color: rgba(124,58,237,0.40); }
.zen-scope.a-dc.a-active, .ob-scope.a-dc.a-active
                                                 { border-color: rgba(124,58,237,0.85); box-shadow: 0 0 40px rgba(124,58,237,0.15); }

/* Scope label sitting on the top edge (fieldset-legend style) */
.zen-scope-label, .ob-scope-label {
    position: absolute;
    top: -14px; left: 20px;
    background: var(--bg);
    font-size: 0.82rem;
    font-weight: 700;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    padding: 2px 12px;
    border-radius: 12px;
    font-family: 'Courier New', monospace;
    color: var(--gray);
    border: 1.5px solid currentColor;
}
.zen-scope.a-agent > .zen-scope-label,
.ob-scope.a-agent  > .ob-scope-label   { color: var(--orange); }
.zen-scope.a-proxy > .zen-scope-label,
.ob-scope.a-proxy  > .ob-scope-label   { color: var(--cyan); }
.zen-scope.a-auth  > .zen-scope-label,
.ob-scope.a-auth   > .ob-scope-label   { color: var(--green); }
.zen-scope.a-idp   > .zen-scope-label,
.ob-scope.a-idp    > .ob-scope-label   { color: var(--violet); }
.zen-scope.a-wds   > .zen-scope-label,
.ob-scope.a-wds    > .ob-scope-label   { color: var(--blue); }
.zen-scope.a-dc    > .zen-scope-label,
.ob-scope.a-dc     > .ob-scope-label   { color: var(--violet); }

/* Direct-child component inside a scope becomes a grid item (no absolute). */
.zen-scope > .zen-box, .zen-scope > .abox,
.ob-scope  > .zen-box, .ob-scope  > .abox {
    position: relative;
    left: auto; top: auto; right: auto; bottom: auto;
    width: auto;
    height: auto;
}

/* data-size="auto" = clear any inline fixed width/height */
[data-size="auto"] {
    width: auto;
    height: auto;
}

/* ===== HUD primitives (fixed — not affected by camera) =================== */
.z-hud-title, .o-hud-title {
    position: fixed; top: 32px; left: 50%;
    transform: translateX(-50%);
    font-size: 1.3rem; font-weight: 600;
    color: var(--white);
    letter-spacing: 1px;
    z-index: 10; text-align: center;
    opacity: 0; transition: opacity 0.5s;
}
.z-hud-title.show, .o-hud-title.show { opacity: 1; }

.z-hud-sub, .o-hud-sub {
    position: fixed; top: 66px; left: 50%;
    transform: translateX(-50%);
    font-size: 0.95rem; color: var(--gray);
    z-index: 10; max-width: 70%; text-align: center;
    opacity: 0; transition: opacity 0.5s;
}
.z-hud-sub.show, .o-hud-sub.show { opacity: 1; }

.z-hud-step, .o-hud-step {
    position: fixed; bottom: 36px; left: 50%;
    transform: translateX(-50%);
    background: rgba(13, 17, 23, 0.85);
    border: 1px solid var(--border);
    border-radius: 40px;
    padding: 10px 22px;
    display: flex; gap: 10px; align-items: center;
    font-size: 0.85rem; color: var(--gray);
    z-index: 10;
}
.z-hud-step .pill, .o-hud-step .pill {
    width: 8px; height: 8px; border-radius: 50%;
    background: var(--border);
    transition: all 0.3s;
}
.z-hud-step .pill.active, .o-hud-step .pill.active { background: var(--cyan); transform: scale(1.4); }
.z-hud-step .pill.past,   .o-hud-step .pill.past   { background: var(--gray); }

.z-progress, .o-progress {
    position: fixed; top: 0; left: 0;
    height: 3px;
    background: linear-gradient(90deg, var(--green), var(--cyan), var(--violet));
    z-index: 100;
    transition: width 0.5s ease-out;
}

/* ===== HUD banner (opt-in, v0.1.1) =========================================
 * A top-of-viewport chrome band that reserves a clear visual zone for the
 * title / subtitle / step counter. Use INSTEAD OF the floating
 * .z-hud-title + .z-hud-sub pair when you want the HUD to clearly stand
 * apart from the scene (avoids "text overlaying boxes" when actors sit high
 * in the world).
 *
 *   <header class="z-hud-bar">
 *       <div class="z-hud-bar__title" id="hudTitle"></div>
 *       <div class="z-hud-bar__sub"   id="hudSub"></div>
 *       <div class="z-hud-bar__step">
 *           <span class="z-hud-bar__step-num"   id="hudStepNum">1</span>
 *           <span class="z-hud-bar__step-sep">/</span>
 *           <span class="z-hud-bar__step-total" id="hudStepTotal">5</span>
 *       </div>
 *   </header>
 *
 * Iframe / embed behaviour: add `body.no-hud` to hide the whole HUD stack
 * (banner + floating variants + progress + step pills). Modules typically
 * set this automatically when window.self !== window.top, unless the URL
 * forces `?hud=on`. This lets a module be embedded inside a host scenario
 * (e.g. via <iframe>) without duplicating chrome.
 * ========================================================================= */
.z-hud-bar {
    position: fixed; top: 0; left: 0; right: 0;
    padding: 18px 28px 22px;
    background:
        linear-gradient(180deg,
            rgba(13, 17, 23, 0.94) 0%,
            rgba(13, 17, 23, 0.82) 55%,
            rgba(13, 17, 23, 0.00) 100%);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    z-index: 9;
    pointer-events: none;
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    grid-template-rows: auto auto;
    column-gap: 16px;
    row-gap: 2px;
    align-items: center;
    opacity: 0;
    transition: opacity 0.5s var(--ease-natural);
}
.z-hud-bar.show { opacity: 1; }

.z-hud-bar__title {
    grid-column: 2; grid-row: 1;
    font-size: 1.15rem;
    font-weight: 600;
    letter-spacing: 0.8px;
    color: var(--white);
    text-align: center;
}

.z-hud-bar__sub {
    grid-column: 2; grid-row: 2;
    font-size: 0.9rem;
    color: var(--gray);
    text-align: center;
    max-width: 70vw;
    justify-self: center;
}

.z-hud-bar__step {
    grid-column: 3; grid-row: 1 / span 2;
    justify-self: end;
    align-self: center;
    padding: 6px 14px;
    border: 1px solid var(--border);
    border-radius: 40px;
    background: rgba(13, 17, 23, 0.55);
    font-family: 'Courier New', monospace;
    font-size: 0.78rem;
    letter-spacing: 0.6px;
    color: var(--gray);
    white-space: nowrap;
}
.z-hud-bar__step-num   { color: var(--cyan); font-weight: 700; }
.z-hud-bar__step-sep   { opacity: 0.5; margin: 0 4px; }
.z-hud-bar__step-total { color: var(--white); font-weight: 600; }

/* Escape hatch — hide the entire HUD stack (banner + floating variants +
 * progress bar + step pills). Modules add this to <body> when embedded in
 * an iframe so the host scenario owns the chrome. */
body.no-hud .z-hud-bar,
body.no-hud .z-hud-title,
body.no-hud .z-hud-sub,
body.no-hud .z-hud-step,
body.no-hud .z-progress,
body.no-hud .z-autoplay-btn,
body.no-hud .o-hud-title,
body.no-hud .o-hud-sub,
body.no-hud .o-hud-step,
body.no-hud .o-progress {
    display: none !important;
}

/* ===== Autoplay button (opt-in, v0.1.1) ====================================
 * Floating play/pause button, top-right corner of the device viewport (NOT
 * the scaled stage). On a 4:3 iPad it naturally sits in the top letterbox
 * band — exactly where navigational chrome belongs.
 *
 * Auto-injected by `engine.init()` when `zen.autoplay` is available. Can
 * be disabled per-module by setting `window.__autoplay = { button: false }`
 * or globally hidden via `body.no-hud`.
 *
 * States:
 *   default          → play icon visible
 *   .is-playing      → pause icon visible, cyan border (indicates loop armed)
 * ========================================================================= */
.z-autoplay-btn {
    position: fixed;
    top: 18px; right: 18px;
    width: 44px; height: 44px;
    border-radius: 50%;
    background: rgba(13, 17, 23, 0.72);
    border: 1.5px solid var(--border);
    color: var(--white);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    z-index: 20;
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    transition: border-color 0.25s var(--ease-natural),
                background-color 0.25s var(--ease-natural),
                transform 0.25s var(--ease-natural);
    padding: 0;
    outline: none;
    -webkit-tap-highlight-color: transparent;
}
.z-autoplay-btn:hover {
    border-color: var(--gray);
    background: rgba(13, 17, 23, 0.88);
    transform: scale(1.06);
}
.z-autoplay-btn:active { transform: scale(0.96); }
.z-autoplay-btn.is-playing {
    border-color: var(--cyan);
    box-shadow: 0 0 16px rgba(34, 211, 238, 0.35);
}
.z-autoplay-btn svg {
    width: 18px; height: 18px;
    stroke: currentColor;
    fill: currentColor;
    pointer-events: none;
}
.z-autoplay-btn .z-ap-play  { display: block; }
.z-autoplay-btn .z-ap-pause { display: none; }
.z-autoplay-btn.is-playing .z-ap-play  { display: none; }
.z-autoplay-btn.is-playing .z-ap-pause { display: block; }

/* ===== Co-branding bug (opt-in, v0.1.1) ====================================
 * "Teleport by ZenOps" TV-channel-style logo bug, pinned to the device
 * viewport corner (NOT the scaled 1920×1080 stage). Lives in the letterbox
 * band when the stage is height- or width-fitted, same pattern as the HUD
 * bar and the autoplay button — it never creates a gap between stage and
 * logo since it's anchored to the physical screen edge.
 *
 * Place it as a direct child of <body> (NOT inside .z-scene), so the scene's
 * `transform: scale(var(--z-fit))` doesn't re-parent `position:fixed`. If it
 * ends up inside .z-scene it degrades to `absolute` relative to the stage —
 * which is the bug we're fixing here.
 *
 *   <body>
 *       <div class="z-scene">...</div>
 *       <div class="z-brand-bug">
 *           <span class="z-brand-bug__primary-label">Teleport</span>
 *           <img class="z-brand-bug__primary" src=".../teleport.svg" alt="">
 *           <span class="z-brand-bug__by">by</span>
 *           <img class="z-brand-bug__secondary" src=".../zenops.svg" alt="ZenOps">
 *       </div>
 *   </body>
 *
 * Variants:
 *   .z-brand-bug--tl / --tr / --br          corner (default: bl)
 *   body.no-hud hides it (same pattern as HUD + autoplay button)
 * ========================================================================= */
.z-brand-bug {
    position: fixed;
    bottom: 18px; left: 22px;
    display: flex;
    align-items: center;
    gap: 12px;
    z-index: 15;
    pointer-events: none;
    opacity: 0.82;
    transition: opacity 0.4s var(--ease-natural);
}
.z-brand-bug--tl { top: 18px;    left: 22px;  bottom: auto; right: auto; }
.z-brand-bug--tr { top: 18px;    right: 22px; bottom: auto; left: auto; }
.z-brand-bug--br { bottom: 18px; right: 22px; top: auto;   left: auto; }

.z-brand-bug__primary {
    height: 36px; width: auto;
    display: block;
}
.z-brand-bug__primary-label {
    font-size: 1.2rem;
    font-weight: 600;
    color: var(--white);
    font-family: 'Segoe UI', system-ui, sans-serif;
    letter-spacing: 0.3px;
}
/* Tighten the wordmark ↔ logomark pair so it reads as a single lockup,
 * while keeping the default 12px gap between the lockup and the "by" +
 * ZenOps block. */
.z-brand-bug__primary-label + .z-brand-bug__primary { margin-left: -4px; }

.z-brand-bug__by {
    font-size: 0.72rem;
    font-weight: 500;
    letter-spacing: 1.8px;
    text-transform: uppercase;
    color: var(--gray);
    font-family: 'Segoe UI', system-ui, sans-serif;
}
.z-brand-bug__secondary {
    height: 22px; width: auto;
    display: block;
}

body.no-hud .z-brand-bug { display: none !important; }
