/* Holon web player: the page that loads the game is the game's own machine powering on.
   Palette, rails, lamps and stamps are lifted from the shell mock the in-game menu was built
   from (CardReferences/review/shell-redesign/era.html), so the loader and the shell are one family.

   Two units, both set by the layout script on :root:
     --u  the game screen's own scale (screen height / 900). Rails use it, so they sit where the
          shell's rails do.
     --k  the content scale: --u with a floor, so a phone held landscape still gets readable type.
   This file is run through Unity's template preprocessor: no line may start with a hash-if,
   and three closing braces in a row would be read as a macro. */

html, body { background: #9AA4B0 }

@font-face {
  font-family: "Michroma";
  src: url("Michroma.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: block;
}

:root {
  --top: 0px;     /* where the loader's rails sit: on the screen's own rails when the window */
  --bottom: 0px;  /* letterboxes top and bottom, at the window edges otherwise */
  --ok: #39C45B;
  --warn: #F0A62C;
  --fault: #E5483B;
  --ink: #161B22;
  --data: "Michroma", "Eurostile", "Bank Gothic", system-ui, sans-serif;
  --sans: "Gill Sans", "Gill Sans MT", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  --u: 1px;
  --k: 1px;
}

* { box-sizing: border-box; margin: 0; padding: 0 }
html, body { width: 100%; height: 100%; overflow: hidden; overscroll-behavior: none }
body {
  position: relative;
  font-family: var(--sans);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  -webkit-text-size-adjust: 100%;
}
button { font: inherit; color: inherit }
[hidden] { display: none !important }

/* ================= the alloy: one face, used by the housing and by the loader ================= */
.alloy {
  background: radial-gradient(120% 80% at 50% -10%, #F4F7FA 0%, #D6DCE4 36%, #AAB3BF 76%, #8C96A3 100%);
}
.alloy::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .55;
  background: repeating-linear-gradient(94deg, rgba(255,255,255,.45) 0 1px,
    rgba(0,0,0,.045) 1px 3px, transparent 3px 5px);
}
.alloy::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(107deg, transparent 16%, rgba(255,255,255,.55) 33%,
    rgba(255,255,255,.1) 45%, transparent 60%);
}

/* the housing is the whole window; the game screen is set into it at 16:9 */
#holon-housing {
  position: fixed; inset: 0; overflow: hidden;
  /* the layout script reads these back as the safe area the screen must stay inside */
  padding: env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px)
           env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px);
}

.rivet {
  position: absolute; z-index: 3; width: 9px; height: 9px; border-radius: 50%;
  margin: -4.5px 0 0 -4.5px;
  background: radial-gradient(circle at 34% 30%, #FFF, #AEB6C2 46%, #69717D 100%);
  box-shadow: 0 1px 1px rgba(0,0,0,.45), 0 0 0 1px rgba(0,0,0,.18);
}

/* the screen: a machined slot. Its bevel only shows where the window is not 16:9. */
#unity-container {
  position: absolute; left: 0; top: 0; width: 100%; height: 100%;
  z-index: 2; border-radius: 3px;
  box-shadow: 0 0 0 1px rgba(8,11,15,.75), 0 0 0 2px rgba(255,255,255,.5),
              0 1px 0 2px rgba(255,255,255,.35), 0 16px 34px rgba(0,0,0,.34);
}
#unity-canvas {
  display: block; width: 100%; height: 100%; border-radius: 3px; outline: none;
  background: #000000;
}

/* phones held upright get a word, not a lecture */
#holon-turn {
  position: absolute; left: 0; right: 0; bottom: max(18px, env(safe-area-inset-bottom));
  z-index: 3; text-align: center; display: none;
  font-family: var(--data); font-size: 9px; letter-spacing: .2em; color: #4A5361;
  text-shadow: 0 1px 0 rgba(255,255,255,.6);
}
@media (orientation: portrait) and (pointer: coarse) { #holon-turn { display: block } }

/* ================= the loader ================= */
#holon-loader {
  position: fixed; inset: 0; z-index: 10; overflow: hidden;
  user-select: none; -webkit-user-select: none; cursor: default;
  transition: opacity .52s cubic-bezier(.4, 0, .2, 1);
}
#holon-loader.gone { opacity: 0; pointer-events: none }

.rail {
  position: absolute; left: 0; right: 0; z-index: 6;
  display: flex; align-items: center; gap: 18px;
  padding: 0 max(calc(var(--u) * 30), 14px, env(safe-area-inset-right, 0px)) 0 max(calc(var(--u) * 30), 14px, env(safe-area-inset-left, 0px));
  background: linear-gradient(180deg, #3D444F 0%, #282E37 40%, #1B2027 70%, #333A44 100%);
  box-shadow: 0 1px 0 rgba(255,255,255,.2) inset, 0 -1px 0 rgba(0,0,0,.6) inset,
              0 12px 28px rgba(0,0,0,.3);
}
.rail::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .32;
  background: repeating-linear-gradient(90deg, rgba(255,255,255,.3) 0 1px,
    rgba(0,0,0,.06) 1px 2px, transparent 2px 4px);
}
.rail.top { top: var(--top); height: max(calc(var(--u) * 70), 30px) }
.rail.top::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: -3px; height: 3px;
  background: linear-gradient(180deg, #C9D0DA, #7E8794);
}
.rail.bot {
  bottom: var(--bottom); height: max(calc(var(--u) * 58), 26px);
  background: linear-gradient(180deg, #333A44 0%, #1B2027 34%, #282E37 70%, #3D444F 100%);
}
.rail .sp { flex: 1 }
.stamp {
  font-family: var(--data); text-transform: uppercase; letter-spacing: .14em;
  font-size: max(7.5px, calc(var(--u) * 10.5)); color: #AEB6C2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
  position: relative; z-index: 2;
}

/* the bay between the rails; the nameplate sits in its middle */
.bay {
  position: absolute; left: 0; right: 0; z-index: 4;
  top: calc(var(--top) + max(calc(var(--u) * 70), 30px)); bottom: calc(var(--bottom) + max(calc(var(--u) * 58), 26px));
  display: flex; align-items: center; justify-content: center;
}

/* a nameplate bolted to the panel. The logo is white, and white on brushed silver is a smudge;
   on dark anodised it is the mark. (The shell mock's own words, and its own plate.) */
.plate {
  position: relative; width: calc(var(--k) * 600);
  padding: calc(var(--k) * 34) calc(var(--k) * 44) calc(var(--k) * 28);
  border-radius: calc(var(--k) * 7);
  display: flex; flex-direction: column; align-items: center;
  background: linear-gradient(180deg, #39404A 0%, #242A33 42%, #191E25 72%, #2F3640 100%);
  box-shadow: 0 1px 0 rgba(255,255,255,.22) inset, 0 -1px 0 rgba(0,0,0,.6) inset,
              0 calc(var(--k) * 14) calc(var(--k) * 34) rgba(0,0,0,.36),
              0 0 0 1px rgba(0,0,0,.28);
  animation: plate-in .5s cubic-bezier(.2, .8, .2, 1) both;
}
.plate::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  opacity: .3; background: repeating-linear-gradient(90deg, rgba(255,255,255,.3) 0 1px,
    rgba(0,0,0,.06) 1px 2px, transparent 2px 4px);
}
/* a light that crosses the plate while the machine is busy - it says "working", never "how far" */
.plate::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: linear-gradient(107deg, transparent 38%, rgba(255,255,255,.07) 48%,
    rgba(255,255,255,.015) 54%, transparent 62%) no-repeat;
  background-size: 250% 100%; background-position: 130% 0;
  animation: sheen 4.2s cubic-bezier(.45, 0, .3, 1) .6s infinite;
}
.plate .screw {
  position: absolute; width: calc(var(--k) * 7); height: calc(var(--k) * 7); border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #C9D0DA, #6D7783 50%, #2B313A 100%);
  box-shadow: 0 1px 0 rgba(255,255,255,.12), 0 0 0 1px rgba(0,0,0,.45);
}
.plate .screw.a { left: calc(var(--k) * 11); top: calc(var(--k) * 11) }
.plate .screw.b { right: calc(var(--k) * 11); top: calc(var(--k) * 11) }
.plate .screw.c { left: calc(var(--k) * 11); bottom: calc(var(--k) * 11) }
.plate .screw.d { right: calc(var(--k) * 11); bottom: calc(var(--k) * 11) }

.plate > * { position: relative; z-index: 2 }
.mark {
  display: block; height: calc(var(--k) * 124); width: auto;
  filter: drop-shadow(0 1px 0 rgba(0,0,0,.55));
  -webkit-user-drag: none;
}
.sub {
  font-family: var(--data); text-transform: uppercase; letter-spacing: .26em; padding-left: .26em;
  font-size: max(7px, calc(var(--k) * 10)); color: #A7B0BC; margin-top: calc(var(--k) * 14);
  white-space: nowrap;
}
.groove {
  align-self: stretch; height: 2px; margin: calc(var(--k) * 24) 0 calc(var(--k) * 20);
  background: linear-gradient(180deg, rgba(0,0,0,.55) 0 1px, rgba(255,255,255,.1) 1px 2px);
}

/* the meter: a slot of lamps in the plate. Each lamp is 5% of the download, lit by exactly
   how much of its 5% has arrived. */
.meter {
  align-self: stretch; display: flex; align-items: center; justify-content: space-between;
  height: calc(var(--k) * 32); padding: 0 calc(var(--k) * 14); border-radius: 999px;
  background: linear-gradient(180deg, #0B0E12 0%, #151A20 100%);
  box-shadow: 0 1px 3px rgba(0,0,0,.85) inset, 0 0 0 1px rgba(0,0,0,.4) inset,
              0 1px 0 rgba(255,255,255,.12);
}

/* a status LED, because the era's hardware said things with lamps */
.lamp {
  --c: var(--ok); --on: 0;
  position: relative; flex: none; display: inline-block; border-radius: 50%;
  width: max(8px, calc(var(--k) * 14)); height: max(8px, calc(var(--k) * 14));
  background: radial-gradient(circle at 34% 30%, #F2F5F9, #9AA3AF 55%, #4E5661 100%);
  box-shadow: 0 0 0 1px rgba(0,0,0,.35);
}
.lamp i {
  position: absolute; inset: 23%; border-radius: 50%; display: block;
  background: #283039; box-shadow: 0 1px 2px rgba(0,0,0,.7) inset;
}
.lamp i::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  background: radial-gradient(circle at 38% 34%, #FFFFFF 0%, var(--c) 42%, var(--c) 100%);
  box-shadow: 0 0 calc(var(--k) * 8) var(--c), 0 0 calc(var(--k) * 2) var(--c);
  opacity: var(--on);
}
.lamp.warn { --c: var(--warn); --on: 1 }
.lamp.ok { --c: var(--ok); --on: 1 }
.lamp.fault { --c: var(--fault); --on: 1 }
.meter.fault .lamp { --c: var(--fault) }
.lamp.breathe i::after { animation: breathe 1.5s ease-in-out infinite }

.readout {
  display: flex; align-items: center; justify-content: center;
  gap: calc(var(--k) * 11); margin-top: calc(var(--k) * 18); max-width: 100%;
}
.readout .stamp {
  font-size: max(8.5px, calc(var(--k) * 11.5)); letter-spacing: .2em; color: #DDE3EA;
  font-variant-numeric: tabular-nums;
}
.readout.fault .stamp { color: #FFB8AD }
.readout.ok .stamp { color: #A6F0B6 }

/* the fault panel: what happened, in plain words, and one key */
.fault-box {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  margin-top: calc(var(--k) * 14); max-width: calc(var(--k) * 440);
}
.fault-text {
  font-size: max(12px, calc(var(--k) * 16)); line-height: 1.45; color: #E6EBF1;
}
.fault-detail {
  font-size: max(9.5px, calc(var(--k) * 11)); line-height: 1.4; color: #8E97A3;
  margin-top: calc(var(--k) * 8); max-width: 100%; overflow: hidden; text-overflow: ellipsis;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  user-select: text; -webkit-user-select: text; word-break: break-word;
}

/* the shell's CTA: one plate, machined, with a real throw */
.cta {
  margin-top: calc(var(--k) * 20); cursor: pointer; border: 1px solid #fff;
  border-radius: calc(var(--k) * 4);
  padding: max(8px, calc(var(--k) * 13)) max(22px, calc(var(--k) * 34)) max(7px, calc(var(--k) * 11));
  display: inline-flex; align-items: center; justify-content: center; gap: calc(var(--k) * 12);
  color: #10151C;
  background: linear-gradient(180deg, #FFFFFF 0%, #DCE2EA 40%, #AFB8C4 52%, #E9EEF3 100%);
  box-shadow: 0 calc(var(--k) * 4) 0 rgba(0,0,0,.5), 0 calc(var(--k) * 12) calc(var(--k) * 24) rgba(0,0,0,.45),
              0 1px 0 rgba(255,255,255,.95) inset;
}
.cta .lg {
  font-family: var(--data); font-size: max(11px, calc(var(--k) * 15));
  letter-spacing: .3em; padding-left: .3em;
}
.cta .tri { font-size: max(9px, calc(var(--k) * 12)); opacity: .75 }
.cta:hover { filter: brightness(1.05) }
.cta:active { transform: translateY(calc(var(--k) * 3)); box-shadow: 0 1px 0 rgba(0,0,0,.45) }
.cta:focus-visible, .key:focus-visible { outline: 1.5px solid rgba(255,255,255,.6); outline-offset: 3px }

/* ================= notices: Unity's banner, said on a strip of the same machine =============== */
#unity-warning {
  position: fixed; z-index: 20; left: 50%; transform: translateX(-50%);
  top: calc(var(--top) + max(calc(var(--u) * 70), 30px) + 12px);
  width: min(calc(100% - 24px), 620px);
  display: flex; flex-direction: column; gap: 8px; pointer-events: none;
}
.notice {
  pointer-events: auto; display: flex; align-items: center; gap: 12px;
  padding: 10px 14px 10px 13px; border-radius: 6px; color: #DDE3EA;
  background: linear-gradient(180deg, #39404A 0%, #242A33 42%, #191E25 72%, #2F3640 100%);
  box-shadow: 0 1px 0 rgba(255,255,255,.2) inset, 0 -1px 0 rgba(0,0,0,.6) inset,
              0 10px 24px rgba(0,0,0,.4), 0 0 0 1px rgba(0,0,0,.35);
  animation: notice-in .28s cubic-bezier(.2, .8, .2, 1) both;
  transition: opacity .35s, transform .35s;
}
.notice.out { opacity: 0; transform: translateY(-6px) }
.notice .lamp { width: 13px; height: 13px }
.notice .txt { flex: 1; min-width: 0 }
.notice .hd { display: block; font-family: var(--data); font-size: 10px; letter-spacing: .16em; color: #FFCD73 }
.notice.fault .hd { color: #FFB8AD }
.notice.info .hd { color: #B7C0CC }
.notice .bd { display: block; font-size: 13.5px; line-height: 1.4; color: #C9D1DC; margin-top: 3px;
  overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  word-break: break-word }
.notice .keys { display: flex; gap: 6px; flex: none }
.key {
  cursor: pointer; font-size: 13px; color: #E6EBF1; padding: 7px 12px; border-radius: 4px;
  background: linear-gradient(180deg, #464E5A, #2A313B); border: 1px solid rgba(255,255,255,.18);
  box-shadow: 0 2px 0 rgba(0,0,0,.45), 0 1px 0 rgba(255,255,255,.16) inset;
}
.key:hover { background: linear-gradient(180deg, #525B68, #333B46) }
.key.light {
  color: #10151C; border-color: #fff;
  background: linear-gradient(180deg, #FFFFFF 0%, #DCE2EA 40%, #AFB8C4 52%, #E9EEF3 100%);
}
.key.light:hover { filter: brightness(1.05) }

/* development builds only: Unity's diagnostics and profiler controls, tucked in a corner */
#holon-devtray {
  position: fixed; z-index: 30; right: 8px; bottom: 8px;
  display: flex; align-items: center; gap: 6px;
}
#diagnostics-icon { display: block; cursor: pointer; width: 28px; height: 28px }

@keyframes plate-in { from { opacity: 0; transform: translateY(8px) } to { opacity: 1; transform: none } }
@keyframes sheen { 0% { background-position: 130% 0 } 60%, 100% { background-position: -30% 0 } }
@keyframes breathe { 0%, 100% { opacity: 1 } 50% { opacity: .35 } }
@keyframes notice-in { from { opacity: 0; transform: translateY(-8px) } to { opacity: 1; transform: none } }

/* compact: the plate on a short screen with a fault to show */
.plate.compact { padding-top: calc(var(--k) * 22); padding-bottom: calc(var(--k) * 20) }
.plate.compact .mark, .plate.compact .sub, .plate.compact .groove, .plate.compact .fault-detail { display: none }
.plate.compact .fault-box { margin-top: calc(var(--k) * 10) }
.plate.compact .cta { margin-top: calc(var(--k) * 14) }

#holon-loader.settled .plate::before { animation: none; opacity: 0 }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition-duration: .01s !important }
  #holon-loader { transition: opacity .12s linear !important }
  .plate::before { display: none }
}

/* the loader's own rivets: the shell mock's, just inside the rails */
#holon-loader .rivet.at-tl, #holon-loader .rivet.at-tr { top: calc(var(--top) + max(calc(var(--u) * 70), 30px) + 12px) }
#holon-loader .rivet.at-bl, #holon-loader .rivet.at-br { bottom: calc(var(--bottom) + max(calc(var(--u) * 58), 26px) + 8px) }
#holon-loader .rivet.at-tl, #holon-loader .rivet.at-bl { left: max(17px, calc(env(safe-area-inset-left, 0px) + 13px)) }
#holon-loader .rivet.at-tr, #holon-loader .rivet.at-br { right: max(17px, calc(env(safe-area-inset-right, 0px) + 13px)) }
