/* ── Asset Forge Cosmic Cyber Theme ── */
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,400;1,600&display=swap');

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  --bg: #06020f;
  --panel: #0d051c;
  --panel-elev: #15092a;
  --neon-cyan: #00e5ff;
  --neon-purple: #8b24ff;
  --neon-pink: #ec4899;
  --white: #ffffff;
  --white-10: rgba(255, 255, 255, 0.10);
  --white-20: rgba(255, 255, 255, 0.20);
  --white-40: rgba(255, 255, 255, 0.40);
  --white-60: rgba(255, 255, 255, 0.60);
  --border-neon: rgba(0, 229, 255, 0.3);
}

html, body {
  min-height: 100%;
  background: var(--bg);
  color: var(--white);
  font-family: 'Montserrat', sans-serif;
  -webkit-font-smoothing: antialiased;
  user-select: none; -webkit-user-select: none;
  /* Mobile Safari/Chrome paint a translucent highlight rectangle over a button the
     instant it's tapped — invisible in desktop mouse testing and in computed styles
     (it's a separate compositor overlay, not a box-shadow/border/outline), but shows
     up on a real touch device as a tinted rim hugging the tapped element's shape. */
  -webkit-tap-highlight-color: transparent;
  /* Without this, mobile browsers auto-boost font sizes inside narrow fixed-width
     panels (like the account panel) regardless of the font-size we actually set. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

/* Custom Cosmic Scrollbars */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: rgba(139, 36, 255, 0.4); border-radius: 999px; }
::-webkit-scrollbar-thumb:hover { background: rgba(0, 229, 255, 0.7); }
* { scrollbar-width: thin; scrollbar-color: rgba(139, 36, 255, 0.4) transparent; }

/* ── Fixed Back to Home button on bottom-right ── */
.af-back {
  position: fixed;
  bottom: 24px;
  right: 24px;
  z-index: 200;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  background: rgba(16, 6, 36, 0.85);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1.5px solid rgba(0, 229, 255, 0.35);
  border-radius: 12px;
  color: #fff;
  text-decoration: none;
  font-family: 'Montserrat', sans-serif;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.6), 0 0 15px rgba(0, 229, 255, 0.15);
  transition: all 0.25s ease;
}

.af-back:hover {
  border-color: var(--neon-cyan);
  background: rgba(28, 12, 60, 0.95);
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.7), 0 0 25px rgba(0, 229, 255, 0.4);
  transform: translateY(-2px);
}

/* ══════════════════ Cosmic Cyber Portal Gate ══════════════════ */
#af-auth-stage {
  position: relative;
  min-height: 100vh;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #06020f;
  overflow: hidden;
}
#af-auth-stage[hidden], #af-auth-stage.hidden {
  display: none !important;
}

.af-portal-bg {
  position: absolute;
  inset: 0;
  background: url('../assets/asset-forge/portal_hero_bg.webp') center center / cover no-repeat;
  filter: brightness(0.9) contrast(1.1);
  z-index: 1;
}

.af-portal-vortex {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 950px;
  height: 950px;
  background: radial-gradient(circle, rgba(139, 36, 255, 0.28) 0%, rgba(0, 229, 255, 0.15) 35%, transparent 70%);
  filter: blur(60px);
  pointer-events: none;
  z-index: 2;
  animation: vortexPulse 8s ease-in-out infinite alternate;
}

@keyframes vortexPulse {
  0% { transform: translate(-50%, -50%) scale(0.95); opacity: 0.8; }
  100% { transform: translate(-50%, -50%) scale(1.1); opacity: 1; }
}

#cosmicParticlesCanvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 3;
}

.af-portal-bottom-glow {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 440px;
  background: radial-gradient(ellipse 85% 70% at 50% 100%, rgba(0, 229, 255, 0.35) 0%, rgba(139, 36, 255, 0.28) 35%, rgba(236, 72, 153, 0.14) 65%, transparent 85%);
  pointer-events: none;
  z-index: 3;
  filter: blur(40px);
  animation: bottomGlowPulse 6s ease-in-out infinite alternate;
}

@keyframes bottomGlowPulse {
  0% { opacity: 0.75; transform: scaleY(0.9); }
  100% { opacity: 1; transform: scaleY(1.15); }
}

.af-portal-overlay {
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at center, transparent 30%, rgba(6, 2, 15, 0.45) 75%, rgba(6, 2, 15, 0.95) 100%);
  pointer-events: none;
  z-index: 4;
}

/* Big 3D Glass Icon Floating Cards */
.af-float-card {
  position: absolute;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 20px 12px 14px;
  background: rgba(18, 8, 38, 0.8);
  backdrop-filter: blur(28px);
  -webkit-backdrop-filter: blur(28px);
  border: 1.5px solid rgba(0, 229, 255, 0.4);
  border-radius: 18px;
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.7), 0 0 25px rgba(139, 36, 255, 0.35);
  pointer-events: auto;
  cursor: default;
  transition: border-color 0.3s ease, box-shadow 0.3s ease;
  will-change: transform;
}

.af-float-card:hover {
  border-color: var(--neon-cyan);
  box-shadow: 0 25px 60px rgba(0, 0, 0, 0.85), 0 0 35px rgba(0, 229, 255, 0.6);
}

.af-float-tl { top: 10%; left: 6%; }
.af-float-tr { top: 12%; right: 6%; }
.af-float-bl { bottom: 18%; left: 8%; }
.af-float-br { bottom: 20%; right: 10%; }

@media (max-width: 1180px) {
  .af-float-card { display: none; }
}

.float-img-icon {
  width: 54px;
  height: 54px;
  object-fit: contain;
  filter: drop-shadow(0 0 14px rgba(0, 229, 255, 0.5));
  flex-shrink: 0;
}

.float-link-icon {
  width: 54px;
  height: 54px;
  border-radius: 16px;
  background: linear-gradient(135deg, rgba(139, 36, 255, 0.4), rgba(0, 229, 255, 0.3));
  border: 1.5px solid rgba(0, 229, 255, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 0 22px rgba(0, 229, 255, 0.4);
  flex-shrink: 0;
}

.float-meta {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.float-title {
  font-family: 'Montserrat', sans-serif;
  font-size: 13.5px;
  font-weight: 800;
  color: #fff;
  letter-spacing: 0.02em;
}

.float-sub {
  font-size: 11px;
  font-weight: 500;
  color: rgba(0, 229, 255, 0.85);
  display: flex;
  align-items: center;
  gap: 5px;
}

.pulse-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #00e5ff;
  box-shadow: 0 0 10px #00e5ff;
  display: inline-block;
}

.af-stage {
  position: relative;
  z-index: 10;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 40px 20px;
  gap: 28px;
  max-width: 600px;
  width: 100%;
}

/* ── Center Cyber Portal Card ──
   A gradient border-box + padding-box fill (rather than the Loginui.png
   frame this used to stretch 100%/100% into place) so the neon edge stays
   a crisp rounded rect at any card height instead of warping to whatever
   aspect ratio the content happens to produce. */
.af-card {
  width: 100%;
  max-width: 480px;
  position: relative;
  background:
    linear-gradient(180deg, rgba(22, 10, 48, 0.92) 0%, rgba(10, 3, 24, 0.96) 100%) padding-box,
    linear-gradient(135deg, rgba(139, 36, 255, 0.85), rgba(0, 229, 255, 0.85)) border-box;
  border: 1.5px solid transparent;
  backdrop-filter: blur(36px);
  -webkit-backdrop-filter: blur(36px);
  border-radius: 32px;
  padding: 38px 34px 32px;
  box-shadow: 
    0 35px 90px rgba(0, 0, 0, 0.85),
    0 0 55px rgba(0, 229, 255, 0.3),
    0 0 110px rgba(139, 36, 255, 0.45);
  transform-style: preserve-3d;
  will-change: transform;
  transition: border-color 0.3s ease, box-shadow 0.3s ease;
}

.af-card:hover {
  box-shadow: 
    0 40px 100px rgba(0, 0, 0, 0.9),
    0 0 75px rgba(0, 229, 255, 0.45),
    0 0 130px rgba(139, 36, 255, 0.55);
}

.af-card-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 14px;
}

.af-logo-header {
  margin-bottom: 2px;
  display: flex;
  justify-content: center;
}

.af-lens-logo-img {
  max-width: 270px;
  width: 85%;
  height: auto;
  object-fit: contain;
  filter: drop-shadow(0 0 20px rgba(0, 229, 255, 0.55));
}

.af-hero-sub {
  font-size: 13px;
  font-weight: 400;
  line-height: 1.65;
  color: rgba(255, 255, 255, 0.78);
  max-width: 400px;
  margin: 0 auto 4px;
}

/* 3 Mode Pills from Lens */
.af-lens-mode-row {
  display: flex;
  gap: 8px;
  justify-content: center;
  flex-wrap: wrap;
  width: 100%;
  margin: 2px 0 8px;
}

.mode-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(139, 36, 255, 0.2);
  border: 1px solid rgba(0, 229, 255, 0.35);
  font-size: 11px;
  font-weight: 700;
  color: #fff;
  box-shadow: 0 0 12px rgba(0, 229, 255, 0.15);
  transition: all 0.25s ease;
}

.mode-pill:hover {
  border-color: var(--neon-cyan);
  background: rgba(0, 229, 255, 0.2);
  box-shadow: 0 0 18px rgba(0, 229, 255, 0.35);
}

.mode-pill img {
  width: 20px;
  height: 20px;
  object-fit: contain;
}

@keyframes pulseGlow {
  0%, 100% { opacity: 0.4; transform: scale(0.9); }
  50% { opacity: 1; transform: scale(1.3); }
}

.af-hero-title {
  font-family: 'Montserrat', sans-serif;
  font-size: 46px;
  font-weight: 900;
  letter-spacing: -0.02em;
  line-height: 1.05;
  background: linear-gradient(180deg, #ffffff 15%, #bdf4ff 50%, #76d6ff 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 0 25px rgba(0, 229, 255, 0.4));
  margin: 2px 0 0;
}

.af-hero-sub {
  font-size: 13px;
  font-weight: 400;
  line-height: 1.65;
  color: rgba(255, 255, 255, 0.72);
  max-width: 400px;
  margin: 0 auto 6px;
}

.af-panel { width: 100%; display: flex; flex-direction: column; gap: 14px; margin-top: 4px; }
.af-panel[hidden] { display: none; }

.af-input-wrap {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.af-label {
  font-family: 'Montserrat', sans-serif;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(0, 229, 255, 0.85);
  text-align: center;
}

.af-input {
  width: 100%;
  background: rgba(8, 3, 20, 0.85);
  border: 1.5px solid rgba(0, 229, 255, 0.35);
  border-radius: 14px;
  padding: 15px 18px;
  color: #fff;
  font-family: 'Montserrat', monospace;
  font-size: 20px;
  font-weight: 700;
  outline: none;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.3em;
  transition: all 0.25s ease;
  box-shadow: inset 0 0 15px rgba(0, 0, 0, 0.6);
}

.af-input:focus {
  border-color: var(--neon-cyan);
  box-shadow: 0 0 25px rgba(0, 229, 255, 0.35), inset 0 0 20px rgba(0, 229, 255, 0.15);
}

.af-btn {
  appearance: none;
  border: none;
  /* Base look for a bare .af-btn with no -primary/-ghost modifier (e.g. the account
     panel's Close button) — without an explicit background here, the browser's native
     button face (near-white) shows through under the color:#fff text below, making it
     unreadable. .af-btn-primary/.af-btn-ghost still override both further down. */
  background: rgba(255, 255, 255, 0.92);
  color: #0a0614;
  border-radius: 14px;
  padding: 15px 22px;
  font-family: 'Montserrat', sans-serif;
  font-size: 14px;
  font-weight: 800;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: all 0.25s ease;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
}

.af-btn-primary {
  background: linear-gradient(135deg, #8b24ff 0%, #2563eb 50%, #00e5ff 100%);
  color: #ffffff;
  box-shadow: 0 8px 30px rgba(139, 36, 255, 0.4), 0 0 20px rgba(0, 229, 255, 0.3);
}

.af-btn-primary:hover {
  filter: brightness(1.15);
  transform: translateY(-2px);
  box-shadow: 0 12px 40px rgba(139, 36, 255, 0.6), 0 0 30px rgba(0, 229, 255, 0.5);
}

.af-btn-ghost {
  border: 1px solid rgba(0, 229, 255, 0.2);
  background: rgba(0, 229, 255, 0.04);
  color: rgba(255, 255, 255, 0.65);
  font-size: 12px;
  font-weight: 600;
  padding: 11px 16px;
}

.af-btn-ghost:hover {
  color: #fff;
  border-color: rgba(0, 229, 255, 0.5);
  background: rgba(0, 229, 255, 0.1);
}

.af-status {
  font-size: 12.5px;
  font-weight: 500;
  color: var(--neon-cyan);
  min-height: 1.2em;
  text-align: center;
}

.af-card-footer {
  margin-top: 4px;
  font-size: 11px;
  color: rgba(255, 255, 255, 0.45);
  display: flex;
  align-items: center;
  gap: 6px;
}

.af-card-footer a {
  color: rgba(0, 229, 255, 0.85);
  text-decoration: none;
  font-weight: 600;
}
.af-card-footer a:hover { color: #fff; text-shadow: 0 0 10px #00e5ff; }

.star-pill {
  color: var(--neon-cyan);
  font-size: 10px;
}

/* ── Account panel (#accountPanel) ── */
.af-account-panel {
  position: fixed;
  top: 14px;
  left: 14px;
  z-index: 150;
  width: 320px;
  max-width: calc(100vw - 28px);
  max-height: calc(100vh - 28px);
  overflow-y: auto;
  background: var(--panel);
  border: 1px solid var(--border-neon);
  border-radius: 16px;
  padding: 22px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.8), 0 0 30px rgba(139, 36, 255, 0.25);
}

.af-account-panel[hidden] { display: none; }

.af-code {
  font-family: 'Montserrat', monospace;
  font-size: 26px;
  font-weight: 800;
  letter-spacing: 0.14em;
  color: #fff;
  text-align: center;
  padding: 8px 0 2px;
}

.af-hint {
  font-size: 12px;
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.55);
  text-align: center;
}

.af-hint-small { font-size: 11px; }

#af-tool-root.hidden { display: none !important; }

/* ════════════════════════════════════════════════════════════════════════
   Texture Grab & 3D Studio Tool Root Styles
   ════════════════════════════════════════════════════════════════════════ */
#af-tool-root{
  --bg:#06020f;
  --bg-panel:#0d051c;
  --bg-elev:#160b2e;
  --border:rgba(0, 229, 255, 0.20);
  --text:#f1f5f9;
  --text-dim:rgba(255, 255, 255, 0.50);
  --mono:#c9cdd3;
  --accent:#00e5ff;
  --accent-gradient: linear-gradient(135deg, #8b24ff 0%, #2563eb 50%, #00e5ff 100%);
  --neon-p:#8b24ff;
  --danger:#ff6b6b;
  --radius:10px;

  background:var(--bg);
  color:var(--text);
  font:14px/1.4 'Montserrat',-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;
  overflow:hidden;
}

/* Everything from here down is the untouched remainder of web/index.html's
   <style> block (from `.mono{...}` to the closing reduced-motion query),
   nested one level inside #af-tool-root — under CSS nesting, a selector
   here with no leading combinator implicitly becomes a descendant selector
   of #af-tool-root, e.g. `button:active{...}` below behaves exactly like
   `#af-tool-root button:active{...}`. No selector text inside this block
   has been edited. */
#af-tool-root{
  .mono{font-family:ui-monospace,"SF Mono","Cascadia Code",Menlo,Consolas,monospace;}
  button, input, select{
    font:inherit;
    color:inherit;
    background:var(--bg-elev);
    border:1px solid var(--border);
    border-radius:var(--radius);
    outline:none;
    box-sizing:border-box;
  }
  button{cursor:pointer;padding:6px 12px;}
  button:hover{border-color:rgba(0, 229, 255, 0.45);}
  button:active{background:#202226;}
  button:disabled{opacity:.4;cursor:default;}

  /* Primary CTAs get seamless purple->blue->cyan gradient with no border line artifacts */
  #btnBrowse, #btnFetchCode, #btnExport, #btnDownloadModel, #btnDownloadAiImage{
    background:var(--accent-gradient);
    color:#fff;
    border:none !important;
    outline:none !important;
    box-shadow:none;
    font-weight:700;
    line-height:1.2;
    padding:7px 14px;
    transition:filter 0.2s ease, transform 0.15s ease;
  }
  #btnBrowse:hover, #btnFetchCode:hover, #btnExport:hover, #btnDownloadModel:hover, #btnDownloadAiImage:hover{
    filter:brightness(1.15);
    border:none !important;
    transform:translateY(-1px);
  }
  #btnBrowse:disabled, #btnFetchCode:disabled, #btnExport:disabled, #btnDownloadModel:disabled, #btnDownloadAiImage:disabled{
    background:var(--bg-elev);
    color:inherit;
    border:1px solid var(--border) !important;
    box-shadow:none;
    transform:none;
  }
  input[type="text"], input[type="number"], select{padding:6px 10px;}
  :focus-visible{outline:2px solid var(--accent);outline-offset:1px;}

  .app{
    display:grid;
    grid-template-columns: 1fr;
    grid-template-rows: auto 1fr 6px auto;
    height:100vh;
  }
  header{
    display:flex;
    align-items:center;
    gap:10px;
    padding:10px 14px;
    border-bottom:1px solid var(--border);
    background:var(--bg-panel);
    flex-wrap:wrap;
  }
  header h1{font-size:14px;font-weight:600;margin:0 12px 0 0;letter-spacing:.02em;}
  .af-header-branding{display:flex;align-items:center;margin-right:12px;flex-shrink:0;}
  .af-header-logo-img{height:20px;width:auto;object-fit:contain;display:block;}
  header .spacer{flex:1;}
  .code-entry{display:flex;gap:6px;align-items:center;}
  .code-entry input{width:8ch;text-transform:uppercase;letter-spacing:.15em;text-align:center;}
  .icon-btn{padding:6px 8px;line-height:1;}

  main{
    display:flex;
    min-height:0;
  }
  @media (max-width: 1100px){
    main{flex-direction:column;overflow-y:auto;}
    .preview-col{min-height:50vh;}
    .resize-handle-v{display:none;}
  }

  /* --- resize handles (drag to resize left/preview/right columns and the library dock) --- */
  .resize-handle-v{
    flex:0 0 6px;
    cursor:col-resize;
    position:relative;
    background:transparent;
  }
  .resize-handle-v::after{
    content:"";
    position:absolute;
    top:0;bottom:0;left:2px;
    width:2px;
    background:var(--border);
  }
  .resize-handle-v:hover::after, .resize-handle-v.dragging::after{background:var(--accent);}
  .resize-handle-h{
    grid-row:3;
    cursor:row-resize;
    position:relative;
    background:transparent;
  }
  .resize-handle-h::after{
    content:"";
    position:absolute;
    left:0;right:0;top:2px;
    height:2px;
    background:var(--border);
  }
  .resize-handle-h:hover::after, .resize-handle-h.dragging::after{background:var(--accent);}

  .left-col{
    flex:0 0 300px;
    min-width:200px;
    max-width:480px;
    display:flex;
    flex-direction:column;
    min-height:0;
    border-right:1px solid var(--border);
    overflow-y:auto;
    scrollbar-width:thin;
    scrollbar-color:var(--accent) var(--bg-panel);
  }
  .left-col::-webkit-scrollbar{width:8px;}
  .left-col::-webkit-scrollbar-track{background:var(--bg-panel);}
  .left-col::-webkit-scrollbar-thumb{background:var(--accent);border-radius:4px;}
  .left-col::-webkit-scrollbar-thumb:hover{filter:brightness(1.2);}
  .preview-col{
    flex:1 1 auto;
    min-width:240px;
    position:relative;
    min-height:0;
    display:flex;
    flex-direction:column;
    background:#08090a;
  }
  .right-col{
    flex:0 0 220px;
    min-width:160px;
    max-width:400px;
    display:flex;
    flex-direction:column;
    min-height:0;
    border-left:1px solid var(--border);
    background:var(--bg-panel);
    overflow-y:auto;
  }

  /* --- library dock (full width, bottom of the window) --- */
  .library-bar{
    border-top:1px solid var(--border);
    background:var(--bg-panel);
    /* height:auto (not a flat 300px) so a sparse library hugs its actual content instead
       of reserving a huge dead strip below/beside the one or two items it has. */
    min-height:120px;
    max-height:80vh;
    overflow-y:auto;
  }

  /* --- Material / Texture sections (right sidebar) --- */
  .side-section{
    padding:12px;
    border-top:1px solid var(--border);
  }
  .side-section:first-child{border-top:none;}
  .side-label{
    display:block;
    margin-bottom:8px;
    font-size:10px;
    letter-spacing:.1em;
    text-transform:uppercase;
    color:var(--text-dim);
  }

  /* --- pipeline strip: stacked top-to-bottom (right sidebar scrolls vertically, not horizontally) --- */
  .strip{
    display:flex;
    flex-direction:column;
    align-items:center;
    gap:10px;
  }
  .strip .arrow{transform:rotate(90deg);}
  .strip .stage{
    flex:0 0 auto;
    width:110px;
    text-align:center;
  }
  .strip .stage .thumb-wrap{
    position:relative;
    width:110px;height:110px;
    border-radius:var(--radius);
    overflow:hidden;
    background:#000;
    border:1px solid var(--border);
  }
  .strip .stage canvas{width:100%;height:100%;display:block;image-rendering:pixelated;}
  .strip .stage .label{
    margin-top:4px;
    font-size:10px;
    letter-spacing:.08em;
    color:var(--text-dim);
    text-transform:uppercase;
  }
  .strip .stage .dl{
    position:absolute;
    top:4px;right:4px;
    width:20px;height:20px;
    padding:0;
    display:flex;align-items:center;justify-content:center;
    background:rgba(10,10,10,.6);
    border-color:rgba(255,255,255,.15);
    font-size:11px;
    opacity:0;
    transition:opacity .12s ease;
  }
  .strip .stage .thumb-wrap:hover .dl,.strip .stage .dl:focus-visible{opacity:1;}
  .maps-group{
    flex:0 0 auto;
    display:flex;
    flex-direction:column;
    align-items:center;
    gap:10px;
  }
  .arrow{
    align-self:center;
    color:var(--text-dim);
    font-size:16px;
    flex:0 0 auto;
  }

  /* --- sliders --- */
  .controls{padding:12px;display:flex;flex-direction:column;gap:14px;flex:1;}
  fieldset{
    border:1px solid var(--border);
    border-radius:var(--radius);
    padding:10px 10px 12px;
  }
  legend{
    padding:0 6px;
    font-size:10px;
    text-transform:uppercase;
    letter-spacing:.1em;
    color:var(--text-dim);
  }
  .row{
    display:grid;
    grid-template-columns: 1fr auto;
    align-items:center;
    gap:10px;
    margin-top:8px;
  }
  .row:first-of-type{margin-top:2px;}
  .row label{font-size:12px;color:var(--text-dim);}
  /* width was 4.5ch — with this box's own 2px/3px padding included (border-box), that left
     room for barely 3 visible characters, clipping anything like "-2.00" or "8.00". */
  .row .val{font-size:11px;font-family:ui-monospace,"SF Mono","Cascadia Code",Menlo,Consolas,monospace;color:var(--mono);width:6ch;text-align:center;padding:3px 4px;flex-shrink:0;}
  /* No stepper arrows on the editable slider value — typing is the only way in, matches request */
  .row .val::-webkit-outer-spin-button, .row .val::-webkit-inner-spin-button{-webkit-appearance:none;margin:0;}
  .row .val{-moz-appearance:textfield;}
  .row input[type="range"]{grid-column:1/-1;width:100%;accent-color:var(--accent);}
  .row.checkbox{grid-template-columns:auto 1fr;}
  .row.checkbox input[type="checkbox"]{accent-color:var(--accent);}
  /* #modelControlsPanel's sliders are siblings of .row (not nested inside it, unlike
     the texture pipeline's JS-built rows above), so .row input[type="range"] never
     matched them — they were falling back to the browser's default blue accent-color
     instead of the site's cyan. */
  #modelControlsPanel input[type="range"]{display:block;width:100%;margin-top:6px;accent-color:var(--accent);}
  #modelControlsPanel input[type="checkbox"]{accent-color:var(--accent);}

  /* --- library (grab gallery) --- */
  .library{
    padding:12px;
    flex:0 0 auto;
  }
  .library-header{
    display:flex;
    flex-wrap:wrap;
    align-items:center;
    gap:8px;
    margin-bottom:10px;
  }
  .library-header .lib-title{
    font-size:10px;
    letter-spacing:.1em;
    color:var(--text-dim);
    text-transform:uppercase;
    flex:0 0 auto;
  }
  .lib-header-controls{
    margin-left:auto;
    display:flex;
    flex-wrap:wrap;
    align-items:center;
    gap:8px;
  }
  /* Matches the border-line fix on Browse/Fetch/Export etc. above — no boxed outline
     in either state, just the active-state gradient swap. */
  #btnLibSelect, #btnLibSelect:hover{border:none !important;}
  #btnLibSelect.active{background:var(--accent-gradient);color:#fff;border-color:transparent;}
  .library-delete-row{
    display:flex;
    align-items:center;
    justify-content:space-between;
    gap:8px;
    margin-bottom:10px;
    font-size:11px;
    color:var(--text-dim);
  }
  button.danger{border-color:rgba(255,107,107,.5);color:var(--danger);}
  button.danger:hover{border-color:var(--danger);background:rgba(255,107,107,.08);}
  .lib-grid{
    display:grid;
    /* Fixed-width tracks (not minmax(...,1fr)) so a sparse library doesn't stretch its
       one or two cards across the whole row width, leaving a huge stark-empty gap that
       reads as broken rather than "just an empty library". */
    grid-template-columns:repeat(auto-fill, 64px);
    gap:10px;
    max-height:240px;
    overflow-y:auto;
    /* overflow-y:auto forces overflow-x to auto too, turning this into a scroll box on
       both axes — anything positioned outside a card's own box (like the select-mode
       checkbox badge) would get clipped by that box without this padding. */
    padding:6px;
  }
  .lib-card{
    display:flex;
    flex-direction:column;
    align-items:center;
    gap:4px;
    cursor:pointer;
    position:relative;
  }
  .lib-card .lib-thumb{
    width:56px;height:56px;
    border-radius:var(--radius);
    overflow:hidden;
    background:#000;
    border:1px solid var(--border);
  }
  .lib-card.active .lib-thumb{border-color:var(--accent);}
  .lib-card .lib-thumb canvas{width:100%;height:100%;display:block;}
  .lib-card .lib-label{font-size:9px;color:var(--text-dim);}
  .lib-card .lib-check{
    position:absolute;
    top:2px;left:2px;
    width:16px;height:16px;
    border-radius:50%;
    border:1px solid var(--border);
    background:var(--bg-elev);
    display:flex;align-items:center;justify-content:center;
    font-size:10px;
    color:transparent;
    z-index:1;
  }
  .lib-card.selected .lib-check{background:var(--accent-gradient);border-color:transparent;color:#fff;}
  .lib-empty{
    padding:20px 0;
    text-align:center;
    color:var(--text-dim);
    font-size:12px;
  }

  /* --- empty state / dropzone --- */
  .empty-state{
    position:absolute;inset:0;
    z-index:5;
    background:#08090a;
    display:flex;
    flex-direction:column;
    align-items:center;
    justify-content:center;
    gap:14px;
    text-align:center;
    padding:40px 20px;
    color:var(--text-dim);
  }
  .empty-state .big{font-size:15px;color:var(--text);max-width:34ch;}
  .empty-state .hint{font-size:12px;}
  .dropzone-active{
    position:fixed;inset:0;
    background:rgba(90,169,255,.08);
    border:2px dashed var(--accent);
    z-index:50;
    pointer-events:none;
    display:flex;align-items:center;justify-content:center;
    font-size:18px;color:var(--accent);
  }
  .hidden{display:none !important;}

  /* --- preview --- */
  .preview-toolbar{
    display:flex;
    gap:10px;
    align-items:center;
    padding:10px 12px;
    border-bottom:1px solid var(--border);
    flex-wrap:wrap;
  }
  .segmented{display:flex;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;}
  .segmented button{border:none;border-radius:0;border-right:1px solid var(--border);background:transparent;}
  .segmented button:last-child{border-right:none;}
  .segmented button.active{background:var(--accent-gradient);color:#fff;}
  #libKindToggle button{display:inline-flex;align-items:center;gap:6px;}
  .lib-tab-icon{width:14px;height:14px;object-fit:contain;flex-shrink:0;}
  /* overflow:hidden so a zoomed-in AI Gen image (transform:scale on #aiImagePreview) is
     clipped to the preview area instead of bleeding out over the toolbar/library. */
  .preview-canvas-wrap{flex:1;min-height:0;position:relative;overflow:hidden;}
  .preview-canvas-wrap canvas{width:100%;height:100%;display:block;touch-action:none;}
  #aiImagePreview{width:100%;height:100%;object-fit:contain;display:block;background:#000;touch-action:none;}

  /* --- AI Gen image editor (crop / flip / rotate / zoom) --- */
  #aiEditToolbar button{padding:6px 8px;line-height:1;}
  #aiCropActions{display:flex;gap:6px;align-items:center;}
  .ai-crop-box{
    position:absolute;
    border:2px dashed var(--accent);
    box-shadow:0 0 0 9999px rgba(0,0,0,.55);
    cursor:move;
    touch-action:none;
  }
  .ai-crop-handle{
    position:absolute;
    width:10px;height:10px;
    background:var(--accent);
    border-radius:2px;
    touch-action:none;
  }
  .ai-crop-handle.nw{left:-5px;top:-5px;cursor:nwse-resize;}
  .ai-crop-handle.ne{right:-5px;top:-5px;cursor:nesw-resize;}
  .ai-crop-handle.sw{left:-5px;bottom:-5px;cursor:nesw-resize;}
  .ai-crop-handle.se{right:-5px;bottom:-5px;cursor:nwse-resize;}
  .export-row{display:flex;gap:8px;align-items:center;}
  .export-row input[type="text"]{width:16ch;}
  .status{font-size:11px;color:var(--text-dim);min-width:8ch;}

  .settings-panel{
    position:absolute;top:46px;right:14px;
    background:var(--bg-elev);
    border:1px solid var(--border);
    border-radius:var(--radius);
    padding:12px;
    width:280px;
    z-index:40;
    box-shadow:0 10px 30px rgba(0,0,0,.5);
  }
  .settings-panel label{display:block;font-size:11px;color:var(--text-dim);margin-bottom:4px;}
  .settings-panel input{width:100%;margin-bottom:10px;}
  .settings-panel .close-row{display:flex;justify-content:flex-end;}

  @media (prefers-reduced-motion: reduce){
    *{transition:none !important;animation:none !important;}
  }
}

input, select, textarea { user-select: text; -webkit-user-select: text; }

.af-stage .credit-line {
  margin-top: 24px;
  text-align: center;
  font-size: 12px;
  color: var(--white-40);
  font-family: 'DM Sans', sans-serif;
}
.af-stage .credit-line a { color: var(--white-60); text-decoration: none; }
.af-stage .credit-line a:hover { color: var(--white); }

.ctx-menu {
  position: fixed; z-index: 9999; background: var(--panel); border: 1px solid var(--white-20);
  border-radius: 10px; padding: 4px; min-width: 180px; box-shadow: 0 8px 32px rgba(0,0,0,.5);
  font-family: 'DM Sans', sans-serif; font-size: 11px; animation: ctxIn .12s ease; display: none;
}
.ctx-menu.show { display: block; }
.ctx-menu button {
  display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 12px;
  border: 0; background: transparent; border-radius: 7px; cursor: pointer;
  color: var(--white); font-family: inherit; font-size: 11px; transition: background .1s;
}
.ctx-menu button:hover { background: var(--white-06); }
.ctx-menu button svg { flex: 0 0 auto; opacity: .6; }
@keyframes ctxIn { from { opacity: 0; transform: scale(.96); } }
