/* PS4 WEBKIT 13.52 public loader - shared stylesheet (landing + running page).
   Rules are written for the PS4 System Browser: no grid, no clamp(), no CSS
   custom properties. Sizes are vw-based so the layout scales on a TV viewport. */

* { -webkit-box-sizing: border-box; box-sizing: border-box; }

html, body {
  margin: 0; padding: 0; min-height: 100%;
  background: #05070a; color: #e9eef6;
  font: 16px/1.45 "Segoe UI", system-ui, -apple-system, sans-serif;
  -webkit-text-size-adjust: 100%;
}
body { overflow-x: hidden; }

/* ---------- background layers: clip (video) / clip still / user image ---------- */
#bgvid, #bgposter, #bgimg {
  position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 0;
}
#bgvid, #bgposter { display: block; object-fit: cover; }
#bgimg {
  display: none;
  background-position: center center; background-repeat: no-repeat;
  /* Height-fit: the picture is scaled so its HEIGHT equals the screen (1080 on
     the console) and the width follows the same ratio, so the image is always
     full top-to-bottom with no zoom and no vertical crop. A real 1920x1080 upload
     therefore lands pixel-perfect; a smaller one grows until it fills the height.
     Whatever is left at the sides is the clip playing behind. */
  background-size: auto 100%;
  background-color: #05070a;
}
/* a custom image behind the panel needs a little more panel opacity to stay
   readable (the clip-only page keeps the lighter panel) */
body.hasimg #card { background: rgba(8,11,16,.72); }
/* No dark mask over the clip: it is shown exactly as delivered so the motion
   stays visible behind the page. Legibility comes from the panel's own backdrop
   and the title/card text shadows. (body.log still hides it during a chain.) */
#veil { display: none; }

/* ---------- page frame ---------- */
#page {
  position: relative; z-index: 2; min-height: 100vh;
  display: -webkit-box; display: -webkit-flex; display: flex;
  -webkit-flex-direction: column; flex-direction: column;
  -webkit-align-items: center; align-items: center;
  padding: 2.4vh 3vw 1.6vh; text-align: center;
}

#hero { width: 100%; max-width: 1200px; margin: 0 0 1.6vh; }
/* Height-driven type: the 1920x1080 console screen is the reference, so the
   title keeps the same visual weight on any window instead of blowing up with
   the width (6.4vw was ~123px there and swallowed the page). */
#who {
  margin: 0; font-size: 7.6vh; line-height: 1.05; font-weight: 800;
  letter-spacing: .01em; color: #ffffff; word-wrap: break-word; overflow-wrap: break-word;
  /* the outline glow takes its colour from the font itself (currentColor) and
     gains a halo whose tone follows the palette the contrast sampler picked */
  text-shadow: 0 0 1.1vh currentColor, 0 0 2.6vh currentColor, 0 3px 24px rgba(0,0,0,.85);
}
body.lum-light #who {
  text-shadow: 0 0 .7vh rgba(255,255,255,.95), 0 0 1.9vh rgba(0,0,0,.42), 0 3px 20px rgba(0,0,0,.55);
}
#who.rgb {
  -webkit-animation: rgbtext 6s linear infinite;
  animation: rgbtext 6s linear infinite;
}
@-webkit-keyframes rgbtext {
  0% { color: #ff4d4d; } 20% { color: #ffd400; } 40% { color: #4ade80; }
  60% { color: #38bdf8; } 80% { color: #c084fc; } 100% { color: #ff4d4d; }
}
@keyframes rgbtext {
  0% { color: #ff4d4d; } 20% { color: #ffd400; } 40% { color: #4ade80; }
  60% { color: #38bdf8; } 80% { color: #c084fc; } 100% { color: #ff4d4d; }
}

/* ---------- title colour picker: round swatches under the name field ---------- */
.colors { margin: 1.4vh 0 0; }
.colors button {
  width: 3.4vh; height: 3.4vh; min-width: 22px; min-height: 22px;
  padding: 0; border-radius: 50%; cursor: pointer;
  border: 2px solid rgba(255,255,255,.4);
  -webkit-box-shadow: 0 0 .6vh rgba(0,0,0,.5); box-shadow: 0 0 .6vh rgba(0,0,0,.5);
  background: #ffffff;
}
.colors button + button { margin-left: 1.2vh; }
.colors button[data-clr="yellow"] { background: #ffd400; }
.colors button[data-clr="orange"] { background: #ff7a18; }
.colors button[data-clr="blue"]   { background: #38bdf8; }
.colors button[data-clr="white"]  { background: #ffffff; }
.colors button[data-clr="rgb"] {
  background: -webkit-linear-gradient(left, #ff4d4d, #ffd400, #4ade80, #38bdf8, #c084fc);
  background: linear-gradient(90deg, #ff4d4d, #ffd400, #4ade80, #38bdf8, #c084fc);
}
.colors button[data-clr="auto"]   { background: #5b6675; }
.colors button.on {
  border-color: #7fd0a0;
  -webkit-box-shadow: 0 0 1vh rgba(127,208,160,.85); box-shadow: 0 0 1vh rgba(127,208,160,.85);
}
#who.placeholder { color: #b6c2d3; opacity: .8; }
#tag {
  margin: .6vh 0 0; font-size: 2vh; letter-spacing: .24em;
  text-transform: uppercase; color: #a9b6c8;
}

/* ---------- landing card ---------- */
#card {
  width: 100%; max-width: 640px; text-align: left;
  /* deliberately light: the clip stays visible through the panel */
  background: rgba(10,14,20,.55); border: 1px solid rgba(64,86,112,.5); border-radius: 12px;
  padding: 2.2vh 2.2vw;
  box-shadow: 0 18px 60px rgba(0,0,0,.45);
}
.fld { margin: 0 0 1.7vh; }
.lbl {
  display: block; margin: 0 0 .7vh; font-size: 1.15vw; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: #c3cedd;
}
.lbl .opt { font-weight: 400; letter-spacing: 0; text-transform: none; color: #8593a6; }
input[type=text], input[type=file] {
  width: 100%; padding: 1.3vh 1vw; background: #0b1017; color: #e9eef6;
  border: 1px solid #2a3a4c; border-radius: 8px; font: inherit; font-size: 1.35vw;
}
input[type=text]:focus {
  outline: none; border-color: #7fd0a0;
  box-shadow: 0 0 0 2px rgba(127,208,160,.18);
}
.or { margin: .9vh 0; font-size: 1.05vw; color: #7a8798; }
.lbl.mt { margin-top: 1.4vh; }

/* ---------- CUSTOM CACHE header + status chip ---------- */
#cachehead {
  display: -webkit-flex; display: flex;
  -webkit-align-items: center; align-items: center;
  -webkit-justify-content: space-between; justify-content: space-between;
  margin: 0 0 1.8vh; padding: 0 0 1.2vh; border-bottom: 1px solid #23303f;
}
#cachetitle {
  font-size: 1.5vw; font-weight: 800; letter-spacing: .18em;
  text-transform: uppercase; color: #e9eef6;
}
.chip {
  padding: .5vh .9vw; border-radius: 999px; border: 1px solid #2b3a4b;
  background: #16202c; color: #9fb0c4; font-size: .95vw; font-weight: 700;
  letter-spacing: .06em; white-space: nowrap;
}
.chip.ok { border-color: #2f6f4d; background: #12241b; color: #7fd0a0; }
.chip.warn { border-color: #7a6432; background: #241f12; color: #d8c07f; }
.chip.bad { border-color: #7a3f39; background: #241412; color: #d08a7f; }
#cacheactions { display: -webkit-flex; display: flex; -webkit-align-items: center; align-items: center; }
#cacheactions .mini { margin-right: .6vw; }
.mini-sm { padding: .5vh .8vw; font-size: 1vw; }
#addr { margin: .5vh 0 0; font-size: 1.15vw; color: #8fa0b4; letter-spacing: .04em; }
#addr.placeholder { opacity: .65; }

.btnrow { display: -webkit-flex; display: flex; -webkit-align-items: center; align-items: center; }
.btnrow .mini + .mini { margin-left: .7vw; }
/* one column that takes either a pasted URL or a picked file */
.onerow { display: -webkit-flex; display: flex; -webkit-align-items: center; align-items: center; }
.onerow input[type=text] { -webkit-flex: 1 1 auto; flex: 1 1 auto; min-width: 0; }
.onerow .mini { -webkit-flex: 0 0 auto; flex: 0 0 auto; margin-left: .7vw; white-space: nowrap; }
.hidden { display: none !important; }
.mini[disabled] { opacity: .5; cursor: default; }
.mini.wide { display: block; width: 100%; margin: 0 0 .8vh; font-size: 1.25vw; }

/* ---------- creator page (/upload) ---------- */
#uploadcard {
  width: 100%; max-width: 760px; text-align: left;
  background: rgba(12,16,22,.88); border: 1px solid #23303f; border-radius: 12px;
  padding: 2.2vh 2.2vw; box-shadow: 0 18px 60px rgba(0,0,0,.55);
}
#upResult { margin-top: 1.2vh; line-height: 1.5; word-break: break-all; }
#upResult b { color: #7fd0a0; }
code { font-family: Consolas, "Courier New", monospace; color: #a9b6c8; }
.mini {
  padding: 1vh 1.2vw; background: #16202c; color: #cfd9e6;
  border: 1px solid #2b3a4b; border-radius: 8px;
  font: inherit; font-size: 1.15vw; font-weight: 600; cursor: pointer;
}
.mini:active { background: #1d2a38; }
.hint { font-size: 1.05vw; color: #8593a6; }
.hint:empty { display: none; }
.btnrow .hint { margin-left: .9vw; }
.det { font-size: 1.2vw; color: #c3cedd; }
.det b { color: #7fd0a0; }
.det b.off { color: #d8c07f; }
.note { margin: .9vh 0 0; font-size: 1.1vw; color: #d8c07f; }
.note:empty { display: none; }
.go {
  display: block; width: 100%; margin-top: 1.2vh; padding: 2.1vh 1vw;
  background: #2f8f62; color: #f2fff8;
  border: 1px solid #42b57e; border-radius: 10px;
  font: inherit; font-size: 2.1vw; font-weight: 800; letter-spacing: .18em;
  cursor: pointer;
}
.go:active { background: #1f6b48; }
#cache { margin: 1vh 0 0; min-height: 1.4vh; }
#cache.cacheok { color: #7fd0a0; }

/* ---------- running page ---------- */
#spin {
  width: 58px; height: 58px; margin: 4vh auto 0;
  border: 5px solid #23303f; border-top-color: #7fd0a0; border-radius: 50%;
  -webkit-animation: spin .9s linear infinite; animation: spin .9s linear infinite;
}
@-webkit-keyframes spin { to { -webkit-transform: rotate(360deg); } }
@keyframes spin { to { transform: rotate(360deg); } }
#msg { display: none; margin: 4vh auto 0; font-size: 2.2vw; letter-spacing: .06em; }
#wrap { display: none; width: 100%; max-width: 1200px; }
#state { margin: 0 0 1vh; font-size: 1.8vw; font-weight: 700; }
#out {
  display: none;
  margin: 0; padding: 1.4vh 1.2vw; height: 58vh; overflow-y: auto;
  white-space: pre-wrap; text-align: left;
  font: 14px/1.45 Consolas, "Courier New", monospace;
  background: rgba(9,12,17,.9); border: 1px solid #23303f; border-radius: 8px;
}
body.done #spin { display: none; }
body.fail #spin { display: none; }
body.fail #msg { display: block; }
/* ?log=1 -- jb.js replaces body.className, so these must win over inline styles. */
body.log #spin, body.log #msg { display: none !important; }
body.log #bgvid, body.log #bgposter, body.log #bgimg, body.log #veil { display: none !important; }
body.log #wrap { display: block; }
body.log #out { display: block; }
body.log #who { font-size: 3.4vw; }
body.log #hero { margin-bottom: 1.2vh; }
body.log #tag { display: none; }

/* ---------- chain runner (lapse/poops) ---------- */
#runstage { width: 100%; max-width: 1100px; text-align: left; }
#runstage #state { margin: 2.6vh 0 0; font-size: 1.9vw; font-weight: 700; }
#runstage #out { height: 40vh; }
#out.visible { display: block; }

.ok { color: #7fd0a0; }
.bad { color: #d08a7f; }

/* ---------- runner chrome: segmented ring with a neon sweep ----------
   Ten thick blocks arranged in a circle (like the reference circle-loading icon)
   with a blue neon pulse running around them, one block after another. The
   engine's own status text stays hidden in #state/#out (?log=1 shows it); the
   technical line sits under the ring. Blocks are created by app.js. */
#fake {
  position: fixed; left: 0; bottom: 15%; width: 100%; z-index: 3;
  text-align: center; pointer-events: none;
}
#fakeBar {
  position: relative; margin: 0 auto;
  width: 9vh; height: 9vh; min-width: 54px; min-height: 54px;
  border: none; border-radius: 50%;
  -webkit-animation: none; animation: none;
}
#fakeBar i {
  display: block; position: absolute; left: 50%; top: 50%;
  width: 2.3vh; height: 1.35vh; min-width: 9px; min-height: 6px;
  margin: 0; border-radius: .4vh;
  background: #0d2130;
  -webkit-animation: neon 1.5s linear infinite;
  animation: neon 1.5s linear infinite;
}
@-webkit-keyframes neon {
  0% { background: #0d2130; -webkit-box-shadow: none; }
  12% { background: #38bdf8; -webkit-box-shadow: 0 0 .7vh #38bdf8, 0 0 1.8vh #0ea5e9; }
  32% { background: #0d2130; -webkit-box-shadow: none; }
  100% { background: #0d2130; -webkit-box-shadow: none; }
}
@keyframes neon {
  0% { background: #0d2130; box-shadow: none; }
  12% { background: #38bdf8; box-shadow: 0 0 .7vh #38bdf8, 0 0 1.8vh #0ea5e9; }
  32% { background: #0d2130; box-shadow: none; }
  100% { background: #0d2130; box-shadow: none; }
}
/* finished: every block solid, no sweep */
#fakeBar.full i {
  -webkit-animation: none; animation: none;
  background: #7fd0a0; -webkit-box-shadow: 0 0 .6vh #7fd0a0; box-shadow: 0 0 .6vh #7fd0a0;
}
#fakeBar.full.bad i { background: #d08a7f; -webkit-box-shadow: none; box-shadow: none; }
#fakeTxt {
  margin: 1.8vh 0 0; font-size: 1.35vw; letter-spacing: .07em; color: #eef6f1;
  text-shadow: 0 2px 10px rgba(0,0,0,.92), 0 0 2px rgba(0,0,0,.9);
}
/* the engine's own live text is hidden; ?log=1 brings it back */
#runstage #state, #runstage #out { display: none; }
body.log #fake { display: none !important; }
body.log #runstage #state, body.log #runstage #out { display: block !important; }

/* finished: the browser could not close itself, so leave exactly one action */
#bye {
  position: fixed; left: 0; top: 0; width: 100%; height: 100%; z-index: 9;
  background: #000; color: #fff; text-align: center;
  display: -webkit-box; display: -webkit-flex; display: flex;
  -webkit-flex-direction: column; flex-direction: column;
  -webkit-align-items: center; align-items: center;
  -webkit-justify-content: center; justify-content: center;
}
#bye b { font-size: 3.2vw; letter-spacing: .12em; }
#bye span { margin-top: 1.8vh; font-size: 1.35vw; letter-spacing: .24em; color: #8fa0b5; }
.warn { color: #d8c07f; }

/* ---------- credits ---------- */
#credits { margin-top: auto; padding-top: 2.4vh; width: 100%; max-width: 1200px; }
.thanks { margin: 0; font-size: 1.25vw; font-weight: 600; color: #b9c4d4; }
.fine { margin: .5vh 0 0; font-size: .95vw; color: #6f7c8e; }

/* ---------- device adaptation + CUSTOM reveal ----------
   app.js sets body.console (PlayStation), body.pc (desktop/mobile) or body.both
   (unrecognised - show everything rather than hide the wrong half), and adds
   body.custom while the form is open. Nothing but the two buttons and the clip
   is on screen until CUSTOM is pressed. */
#consoleform, #creator, #owner { display: none; }
body.custom.console #consoleform,
body.custom.both #consoleform { display: block; }
body.custom.pc #creator,
body.custom.both #creator { display: block; }
/* the owner rename block also carries the hidden attribute from app.js */
body.custom.console #owner:not([hidden]),
body.custom.both #owner:not([hidden]) { display: block; }
#ownerSave { margin-top: .9vh; }
#ownerNote:empty { display: none; }

/* ---------- usage counter, bottom left ---------- */
.stats {
  position: fixed; left: 1.6vw; bottom: 1.4vh; z-index: 6;
  font: 1.05vw/1.5 Consolas, "Courier New", monospace;
  letter-spacing: .05em; color: #d7e6f7; white-space: pre; text-align: left;
  text-shadow: 0 2px 10px rgba(0,0,0,.9), 0 0 2px rgba(0,0,0,.85);
}
.stats:empty { display: none; }

/* ---------- auto contrast: the text controls the palette ----------
   app.js samples the background every few seconds and adds lum-light (bright
   backdrop) or lum-dark (dark backdrop); these rules make the title, subtitle,
   ring and counter the most visible thing on the page either way. */
body.lum-light #who, body.lum-light #tag, body.lum-light .stats, body.lum-light #fakeTxt {
  color: #0a0f16;
  text-shadow: 0 2px 14px rgba(255,255,255,.8), 0 0 2px rgba(255,255,255,.65);
}
body.lum-light #fakeBar { border-color: rgba(0,0,0,.3); border-top-color: #0a0f16; }
body.lum-light #fakeBar.full { border-color: #146c43; border-top-color: #146c43; }
body.lum-light #fakeBar.full.bad { border-color: #a33f33; border-top-color: #a33f33; }
/* the creator's status line disappears completely while it has nothing to say */
#upstatus { margin: 0; }
#upGo { margin-top: 1.2vh; }
.chip:empty { display: none; }
