/* 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;
  /* contain, not cover: a profile image must FIT the screen - cover zoomed a
     1531x1309 logo up and cropped the wordmark on the PS4. The clip plays
     underneath, so the leftover band is not dead space. */
  background-size: contain;
  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; }
#who {
  margin: 0; font-size: 6.4vw; line-height: 1.06; font-weight: 800;
  letter-spacing: .01em; color: #ffffff; word-wrap: break-word; overflow-wrap: break-word;
  text-shadow: 0 3px 26px rgba(0,0,0,.88), 0 0 2px rgba(0,0,0,.9);
}
#who.placeholder { color: #b6c2d3; opacity: .8; }
#tag {
  margin: .6vh 0 0; font-size: 1.4vw; 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; }
