/* AI Story Film — shared theme & components */
*{box-sizing:border-box;margin:0;padding:0}
:root{
  --ink:#0c0c0e;--ink-2:#141417;--card:#16161a;
  --line:rgba(200,164,92,.22);--line-soft:rgba(244,241,234,.08);
  --paper:#f4f1ea;--muted:#a09a8e;--muted-2:#6f6a60;
  --gold:#c8a45c;--gold-bright:#dcc089;--red:#e05a4e;--green:#4e9e6e;
}
body{zoom:1.15;background:var(--ink);color:var(--paper);font-family:"Hanken Grotesk",sans-serif;font-weight:400;line-height:1.6;min-height:100vh;-webkit-font-smoothing:antialiased;}
/* ── Impersonation banner (admin "Login as" an editor) ──────────────────── */
.impersonate-strip{background:var(--gold);color:#1a1407;font-size:12.5px;font-weight:600;
  letter-spacing:.03em;text-align:center;padding:10px 16px}
.impersonate-strip b{font-weight:800}
.impersonate-strip button{margin-left:10px;background:rgba(26,20,7,.15);
  border:1px solid rgba(26,20,7,.35);border-radius:3px;color:#1a1407;font-size:11px;
  letter-spacing:.08em;text-transform:uppercase;font-weight:700;padding:5px 12px;
  cursor:pointer;font-family:inherit;transition:background .2s}
.impersonate-strip button:hover{background:rgba(26,20,7,.28)}

nav{position:sticky;top:0;z-index:100;backdrop-filter:blur(12px);background:rgba(12,12,14,.88);border-bottom:1px solid var(--line-soft);}
.nav-in{max-width:1200px;margin:0 auto;padding:18px 28px;display:flex;align-items:center;gap:14px;}
.nav-logo{height:50px;object-fit:contain;}
.nav-title{font-family:"Fraunces",serif;font-weight:300;font-size:18px;letter-spacing:-.01em;color:var(--paper);}
.nav-title em{font-style:italic;color:var(--gold-bright);}
.main{max-width:1100px;margin:0 auto;padding:40px 28px 80px;}
.eyebrow{font-size:11px;letter-spacing:.32em;text-transform:uppercase;color:var(--gold);font-weight:600;margin-bottom:14px;}
h2{font-family:"Fraunces",serif;font-weight:300;font-size:clamp(22px,3vw,34px);letter-spacing:-.01em;line-height:1.1;margin-bottom:8px;}
h2 em{font-style:italic;color:var(--gold-bright);}
h3{font-family:"Fraunces",serif;font-weight:300;}
.panel-sub{color:var(--muted);font-size:14px;margin-bottom:30px;}
label{display:block;font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:var(--muted-2);font-weight:500;margin-bottom:7px;}
input,select,textarea{width:100%;background:var(--card);color:var(--paper);border:1px solid var(--line-soft);border-radius:4px;padding:11px 14px;font-family:"Hanken Grotesk",sans-serif;font-size:14px;outline:none;transition:border-color .25s;-webkit-appearance:none;}
input[type="checkbox"],input[type="radio"]{width:auto;-webkit-appearance:checkbox;appearance:auto;accent-color:var(--gold);padding:0;border:none;}
input:focus,select:focus,textarea:focus{border-color:var(--line);}
input:disabled,select:disabled{opacity:.6;cursor:not-allowed;}
.field{margin-bottom:22px;}
.hint{font-size:11px;color:var(--muted-2);margin-top:6px;}
.btn{display:inline-flex;align-items:center;gap:8px;padding:13px 28px;border-radius:3px;border:none;cursor:pointer;font-family:"Hanken Grotesk",sans-serif;font-size:11.5px;letter-spacing:.16em;text-transform:uppercase;font-weight:600;transition:all .25s;text-decoration:none;}
.btn-gold{background:var(--gold);color:#1a1407;} .btn-gold:hover{background:var(--gold-bright);} .btn-gold:disabled{opacity:.4;cursor:not-allowed;}
.btn-ghost{background:transparent;color:var(--muted);border:1px solid var(--line-soft);} .btn-ghost:hover{color:var(--paper);border-color:var(--line);}
.btn-sm{padding:8px 16px;font-size:10.5px;}
/* Header buttons never wrap (⌂ on one line, LAUNCHER on the next) as the nav fills up. */
nav .btn,nav .user-menu-toggle{white-space:nowrap;flex-shrink:0;}
/* When the header is tight, the page title gives way (…) rather than the buttons. */
.nav-top .nav-brand,.nav-in .nav-brand{min-width:0;flex-shrink:1;}
.nav-top .nav-title,.nav-in .nav-title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
nav .btn .nav-ico{width:13px;height:13px;flex-shrink:0;}
.btn-red{background:transparent;color:var(--red);border:1px solid rgba(224,90,78,.3);} .btn-red:hover{background:rgba(224,90,78,.1);}
.btn-gold-outline{background:transparent;color:var(--gold);border:1px solid rgba(200,164,92,.4);} .btn-gold-outline:hover{background:rgba(200,164,92,.1);border-color:var(--gold);}
.highlight-box{background:var(--ink-2);border:1px solid var(--line-soft);border-radius:6px;padding:20px 22px;}
.cmd-box{background:var(--ink);border:1px solid var(--line-soft);border-radius:4px;padding:14px 16px;font-family:monospace;font-size:12.5px;color:var(--gold-bright);word-break:break-all;line-height:1.7;margin-bottom:10px;white-space:pre-wrap;display:-webkit-box;-webkit-line-clamp:5;-webkit-box-orient:vertical;overflow:hidden;}
.banner{font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:var(--gold-bright);background:rgba(200,164,92,.06);border:1px solid var(--line);border-radius:4px;padding:8px 14px;margin-bottom:24px;}
.tag{display:inline-flex;align-items:center;gap:6px;font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--green);background:rgba(78,158,110,.12);border:1px solid rgba(78,158,110,.3);padding:4px 10px;border-radius:3px;}
.log-area{background:var(--ink-2);border:1px solid var(--line-soft);border-radius:4px;padding:14px 16px;font-family:monospace;font-size:11.5px;color:var(--muted);line-height:1.8;max-height:300px;overflow-y:auto;min-height:80px;}
.log-line.head{color:var(--gold-bright);} .log-line.err{color:var(--red);} .log-line.ok{color:var(--green);}
.status{margin-top:16px;font-size:13px;padding:12px 16px;border-radius:4px;}
.status.success{background:rgba(78,158,110,.12);color:var(--green);border:1px solid rgba(78,158,110,.3);}
.status.error{background:rgba(224,90,78,.12);color:var(--red);border:1px solid rgba(224,90,78,.3);}
.status.loading{background:rgba(200,164,92,.1);color:var(--gold-bright);border:1px solid var(--line);}
/* pipeline launcher cards */
.pipeline{display:flex;flex-direction:column;gap:12px;}
.pcard{display:flex;flex-direction:row;align-items:center;gap:20px;background:var(--ink-2);border:1px solid var(--line-soft);border-radius:8px;padding:18px 22px;cursor:pointer;transition:border-color .2s,transform .2s;text-decoration:none;color:inherit;}
.pcard:hover{border-color:var(--gold);transform:translateY(-2px);}
.pcard .picon{flex-shrink:0;color:var(--gold);opacity:.75;}
.pcard:hover .picon{opacity:1;}
.pcard .ptext{display:flex;flex-direction:column;gap:3px;}
.pcard .phead{display:flex;align-items:baseline;gap:8px;}
.pcard .pnum{font-family:"Fraunces",serif;font-size:13px;color:var(--gold);}
.pcard .pttl{font-family:"Fraunces",serif;font-weight:300;font-size:18px;color:var(--paper);}
.pcard .pdesc{font-size:12.5px;color:var(--muted);line-height:1.45;}
.pcard.locked{opacity:.45;cursor:not-allowed;pointer-events:none;}

/* Single user-menu dropdown — consolidates the display name, Accounts,
   Admin, Connection settings, and Sign out behind one "<name> ▾" button
   (see SF.mountNavMenu in common.js), used on every page. Launcher is
   deliberately NOT in here — it stays its own always-visible button in the
   nav row (wherever each page's own markup places it, right after the
   logo/title on every page), since it's frequent primary navigation rather
   than an account/settings action. */
.user-menu{position:relative;margin-left:auto;}
.user-menu-toggle{display:inline-flex;align-items:center;gap:7px;background:transparent;border:1px solid var(--line-soft);border-radius:3px;padding:8px 14px;font-family:"Hanken Grotesk",sans-serif;font-size:11px;letter-spacing:.06em;color:var(--paper);cursor:pointer;transition:border-color .2s,color .2s;}
.user-menu-toggle:hover{border-color:var(--line);}
.user-menu-toggle .chev{transition:transform .18s ease;display:inline-flex;flex-shrink:0;color:var(--muted-2);}
.user-menu-toggle.open .chev{transform:rotate(180deg);}
.user-menu-panel{display:none;position:absolute;top:calc(100% + 8px);right:0;width:300px;max-width:88vw;background:var(--ink-2);border:1px solid var(--line-soft);border-radius:8px;padding:6px;box-shadow:0 12px 32px rgba(0,0,0,.5);z-index:220;}
.user-menu-panel.open{display:block;}
.user-menu-item{display:block;width:100%;text-align:left;background:none;border:none;padding:10px 12px;border-radius:5px;font-family:"Hanken Grotesk",sans-serif;font-size:12.5px;letter-spacing:0;color:var(--paper);text-decoration:none;cursor:pointer;transition:background .15s;}
.user-menu-item:hover{background:rgba(255,255,255,.05);}
.user-menu-item.danger:hover{color:var(--red);}

/* Connection settings — normally its own toggle+popover (see SF.buildConnToggle
   in common.js), but nested a level deeper here: restyled from a pill button
   into a plain menu row, and its panel becomes an inline accordion instead of
   a second floating popover, so the whole thing reads as one dropdown. */
.user-menu-panel #connToggle{display:flex;align-items:center;gap:8px;width:100%;text-align:left;background:none;border:none;border-radius:5px;padding:10px 12px;font-family:"Hanken Grotesk",sans-serif;font-size:12.5px;letter-spacing:0;text-transform:none;font-weight:400;color:var(--paper);cursor:pointer;}
.user-menu-panel #connToggle:hover{background:rgba(255,255,255,.05);}
.user-menu-panel #connToggle .chev{margin-left:auto;}
.user-menu-panel #connPanel{position:static;display:none;width:auto;max-width:none;background:none;border:none;border-radius:0;box-shadow:none;padding:2px 4px 4px 12px;margin:0;}
.user-menu-panel #connPanel.open{display:block;}
#connToggle .chev{transition:transform .18s ease;display:inline-flex;}
#connToggle.open .chev{transform:rotate(180deg);}
#connPanel{display:none;position:absolute;top:calc(100% + 8px);right:0;width:340px;max-width:88vw;background:var(--ink-2);border:1px solid var(--line-soft);border-radius:8px;padding:6px 16px;box-shadow:0 12px 32px rgba(0,0,0,.5);z-index:200;}
#connPanel.open{display:block;}
.conn-row{display:flex;align-items:center;gap:8px;padding:8px 0;border-bottom:1px solid var(--line-soft);font-size:11.5px;}
.conn-row:last-child{border-bottom:none;}
.conn-row .conn-label{width:88px;flex-shrink:0;}
.conn-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0;}
.conn-dot.ok{background:#4e9e6e;}
.conn-dot.warn{background:var(--gold);}
.conn-dot.err{background:#c0392b;}
.conn-dot.checking{background:var(--muted-2);animation:pulse .9s ease-in-out infinite alternate;}
@keyframes pulse{to{opacity:.3;}}
.conn-label{color:var(--muted-2);letter-spacing:.08em;}
.conn-value{color:var(--paper);flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.conn-detail{font-size:10px;color:var(--muted-2);white-space:nowrap;}
.conn-btn{margin-left:6px;font-size:10px;padding:2px 8px;background:none;border:1px solid var(--line-soft);border-radius:3px;color:var(--muted);cursor:pointer;white-space:nowrap;flex-shrink:0;}
.conn-btn:hover{border-color:var(--gold);color:var(--gold);}

/* Claude / ElevenLabs / Suno key-update modals — shared header component, every page */
#claudeKeyModal,#elKeyModal,#sunoKeyModal{display:none;position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:999;align-items:center;justify-content:center;}
#claudeKeyModal.open,#elKeyModal.open,#sunoKeyModal.open{display:flex;}
#claudeKeyModal .modal-box,#elKeyModal .modal-box,#sunoKeyModal .modal-box{background:var(--ink);border:1px solid var(--line-soft);border-radius:8px;padding:28px;width:420px;max-width:90vw;}

/* "Report a bug" modal — shared header component, every page (see SF.mountReportBug) */
#reportBugModal{display:none;position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:999;align-items:center;justify-content:center;}
#reportBugModal.open{display:flex;}
#reportBugModal .modal-box{background:var(--ink);border:1px solid var(--line-soft);border-radius:8px;padding:28px;width:460px;max-width:90vw;}
#reportBugModal label{display:block;font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted-2);margin:14px 0 6px;}
#reportBugModal label:first-of-type{margin-top:0;}
#reportBugModal textarea{min-height:90px;resize:vertical;}

/* Shared confirm modal — replaces window.confirm() everywhere (see SF.confirm
   in common.js for why: native confirm() silently auto-cancels for the rest
   of a page's life once a browser's "prevent this page from creating
   additional dialogs" checkbox has been ticked once, with no visible sign
   anything happened — reads as a dead button). */
/* Above every other fixed overlay on the site (toast 9999, progress-widget
   stack 9998, browse modal 10000) — a confirm dialog is a blocking prompt
   and must never render behind something else's buttons are still
   clickable through. Was 999 before this fix: with the progress widget
   showing, the modal's own backdrop was visible but its OK/Cancel buttons
   sat underneath the widget in click-target order — clicks landed on
   whatever widget card was there instead of the modal. */
#sfNoticeModal{display:none;position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:10001;align-items:center;justify-content:center;}
#sfNoticeModal.open{display:flex;}
#sfNoticeModal .modal-box{background:var(--ink);border:1px solid var(--line-soft);border-radius:8px;padding:30px 30px 26px;width:480px;max-width:90vw;max-height:88vh;overflow:auto;}
#sfNoticeModal h3{margin:0 0 10px;font-family:'Fraunces',serif;font-weight:300;font-size:24px;}
#sfNoticeModal .nbody{font-size:14px;color:var(--paper);line-height:1.6;margin:0 0 18px;}
#sfNoticeModal .nbody p{margin:0 0 12px;}
#sfNoticeModal .nreminder{border:1px solid rgba(200,164,92,.35);background:rgba(200,164,92,.08);border-radius:6px;padding:14px 16px;font-size:13.5px;line-height:1.6;color:var(--paper);margin:0 0 20px;}
#sfNoticeModal .nreminder b{color:var(--gold-bright);}
#sfNoticeModal .nreminder .nr-title{font-family:'Fraunces',serif;font-weight:400;font-size:18px;color:var(--gold-bright);margin:0 0 8px;}
#sfNoticeModal .modal-actions{display:flex;justify-content:flex-end;}
#sfConfirmModal{display:none;position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:10001;align-items:center;justify-content:center;}
#sfConfirmModal.open{display:flex;}
#sfConfirmModal .modal-box{background:var(--ink);border:1px solid var(--line-soft);border-radius:8px;padding:28px;width:420px;max-width:90vw;}
#sfConfirmModal h3{margin:0 0 8px;font-family:'Fraunces',serif;font-weight:300;font-size:20px;}
#sfConfirmModal p{font-size:13px;color:var(--muted);margin:0 0 20px;}
#sfConfirmModal .modal-actions{display:flex;gap:10px;justify-content:flex-end;}

/* Full-screen viewer for a drawn-on review screenshot (SF.lightbox). */
.lightbox-overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,.9);
  z-index:10002;align-items:center;justify-content:center;padding:40px;cursor:zoom-out}
.lightbox-overlay.open{display:flex}
.lightbox-overlay img{max-width:100%;max-height:100%;border-radius:4px;cursor:default;
  box-shadow:0 10px 60px rgba(0,0,0,.6)}
.lightbox-close{position:fixed;top:20px;right:24px;width:40px;height:40px;border-radius:50%;
  border:1px solid var(--line-soft);background:rgba(20,20,23,.85);color:var(--paper);
  font-size:24px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center}
.lightbox-close:hover{border-color:var(--gold);color:var(--gold-bright)}
/* One cell of a grid image, cropped and zoomed to fill the viewer — see
   SF.lightbox's optional crop argument. aspect-ratio is set per-image in
   JS (from the real file's dimensions), so max-width/max-height here just
   cap it to the available screen space same as the plain-image path does. */
.lightbox-crop-frame{display:none;position:relative;overflow:hidden;max-width:100%;max-height:100%;
  border-radius:4px;box-shadow:0 10px 60px rgba(0,0,0,.6)}
#sfLightboxCropImg{position:absolute;top:0;left:0;max-width:none;max-height:none}

/* The card carries its own segmented-control and checkbox styling: these were
   previously defined per page (video-workflow.html), so a card mounted
   anywhere else rendered unstyled. Scoped so no page's own .seg is affected. */
.gen-card .seg{display:flex;border:1px solid var(--line-soft);border-radius:4px;overflow:hidden;}
.gen-card .seg button{background:none;border:none;color:var(--muted);padding:9px 16px;
  font-size:12px;cursor:pointer;font-family:inherit;transition:background .15s,color .15s;}
.gen-card .seg button:hover:not(.on){color:var(--paper);}
.gen-card .seg button.on{background:rgba(200,164,92,.12);color:var(--gold-bright);}
.gen-card .chk{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--paper);
  text-transform:none;letter-spacing:0;cursor:pointer;margin:0;}
.gen-card .chk input{width:auto;accent-color:var(--gold);cursor:pointer;margin:0;}
.gen-card label{margin-bottom:7px;}

/* ── Generation settings card ────────────────────────────────────────────
   One component, two variants: image settings wherever a page generates
   images, video settings wherever it generates video. Everything it offers
   comes from /api/providers, so adding a model never means editing a page. */
.gen-card{background:var(--ink-2);border:1px solid var(--line-soft);border-radius:6px;
  margin-bottom:28px;overflow:hidden;}
.gen-card .gc-head{display:flex;align-items:center;gap:14px;padding:13px 20px;
  border-bottom:1px solid var(--line-soft);}
.gen-card .gc-title{font-family:"Fraunces",serif;font-size:15px;flex:1;}
.gen-card .gc-summary{font-size:12px;color:var(--muted-2);}
.gen-card .gc-summary b{color:var(--gold-bright);font-weight:600;}
/* Top-aligned, not bottom: a field carrying a hint is taller than its
   neighbours, and flex-end would lift its label out of line with theirs. */
.gen-card .gc-body{padding:16px 20px;display:flex;flex-wrap:wrap;gap:22px 22px;align-items:flex-start;}
.gen-card .gc-field.off{opacity:.4;}
.gen-card .gc-field.off select{pointer-events:none;}
.gen-card .gc-why{font-size:10.5px;color:var(--muted-2);margin-top:6px;max-width:190px;line-height:1.45;}
.gen-card select{background:rgba(12,12,14,.6);border:1px solid var(--line-soft);border-radius:4px;
  color:var(--paper);font-size:13px;padding:8px 11px;outline:none;min-width:118px;font-family:inherit;}
.gen-card select:focus{border-color:var(--gold);}
/* The generations counter is the one card control that isn't a provider param,
   but it has to sit in the same row and read as the same kind of thing. */
.gen-card input[type=number]{background:rgba(12,12,14,.6);border:1px solid var(--line-soft);
  border-radius:4px;color:var(--paper);font-family:inherit;font-size:13px;padding:9px 12px;
  width:82px;}
.gen-card input[type=number]:focus{border-color:var(--gold);outline:none;}
/* A count that is set per item elsewhere (per-prompt batches): shown in the
   input's slot, in the input's clothes, but not editable here. */
.gen-card .gc-static{background:rgba(12,12,14,.35);border:1px solid var(--line-soft);border-radius:4px;
  color:var(--muted-2);font-size:13px;padding:9px 12px;min-width:82px;white-space:nowrap;opacity:.6;cursor:default;}
.gen-card .gc-note{padding:10px 20px;border-top:1px solid var(--line-soft);
  background:rgba(200,164,92,.05);font-size:12px;color:var(--gold-bright);}
.gen-card .gc-cost{border-top:1px solid var(--line-soft);padding:13px 20px 15px;
  display:flex;align-items:baseline;gap:12px;}
.gen-card .gc-cost-label{font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:var(--muted-2);}
.gen-card .gc-cost-amt{font-family:"Fraunces",serif;font-size:22px;color:var(--gold-bright);line-height:1;}
.gen-card .gc-cost-amt.dim{font-family:"Hanken Grotesk",sans-serif;font-size:13px;
  color:var(--muted-2);font-style:italic;}
.gen-card .gc-cost-per{font-size:12px;color:var(--muted-2);}
.gen-card .gc-cost-total-row{border-top:1px solid var(--line-soft);padding:10px 20px 13px;}
.gen-card .gc-cost-total{font-size:12px;color:var(--gold-bright);}
/* Page-owned slots: a node under the generations counter, and a footer
   section (summary, submit) that shares the card instead of sitting under it. */
/* The page sets the node's width itself (a fixed width, not a cap: the field
   takes its flex size from the label's unclamped text otherwise, and pushes
   itself onto its own row). */
.gen-card .gc-extra{margin-top:10px;text-transform:none;letter-spacing:0;
  font-weight:400;margin-bottom:0;}
.gen-card .gc-footer{border-top:1px solid var(--line-soft);padding:18px 20px 20px;
  background:rgba(200,164,92,.03);}
.gen-card .gc-footer-title{font-family:"Fraunces",serif;font-weight:300;font-size:17px;margin-bottom:14px;}
/* Jobs / Est. credits strip under the controls (2026-09-23: replaces the
   estimated-cost rows and the pages' own summary grids). */
.gen-card .gc-stats{display:flex;gap:14px;flex-wrap:wrap;padding:14px 20px 16px;border-top:1px solid var(--line-soft);}
.gen-card .gc-stat{flex:0 0 150px;max-width:100%;}
.gen-card .gc-stat .k{font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:var(--muted-2);margin-bottom:6px;}
.gen-card .gc-stat .v{background:rgba(12,12,14,.6);border:1px solid var(--line-soft);border-radius:4px;
  padding:7px 12px;text-align:center;font-family:"Fraunces",serif;font-weight:300;font-size:22px;color:var(--gold-bright);line-height:1.2;}
.gen-card .gc-stat .v.dim{font-family:"Hanken Grotesk",sans-serif;font-size:13px;color:var(--muted-2);padding:11px 12px;}

/* Higgsfield guide: Mac / Windows switch (connect-accounts.html and admin.html) */
.hf-os-win,.hf-os-mac{display:none;}
body.hfos-win .hf-os-win,body.hfos-mac .hf-os-mac{display:block;}
.hf-os-switch{display:flex;align-items:center;gap:6px;margin:0 0 16px;}
.hf-os-switch .lbl{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted-2);margin-right:4px;}
.hf-os-switch button{background:transparent;border:1px solid var(--line);color:var(--muted);border-radius:4px;padding:6px 14px;font-size:12px;cursor:pointer;font-family:inherit;}
.hf-os-switch button:hover{color:var(--paper);border-color:var(--gold);}
body.hfos-win .hf-os-switch [data-hf-os-btn="win"],body.hfos-mac .hf-os-switch [data-hf-os-btn="mac"]{background:rgba(200,164,92,.14);border-color:var(--gold);color:var(--gold-bright);}
