/* Palette, type scale and component styling lifted from updater-gui/theme.py so
   the page and the desktop app are visibly one product. Where a value here
   looks arbitrary it is a pt-to-px conversion of the Qt stylesheet (10pt ≈ 13px
   at 96 dpi), not a fresh choice. */

/* Wonderful Snowflake carries **186 glyphs** — no em-dash, no en-dash, no curly
   apostrophe. Anything it cannot draw renders as a tofu box, so it is a
   **display face only**: the logo fallback, headings, and the primary button.
   All body copy runs in the platform UI font, which can spell. Straight ASCII
   apostrophes are in the font and safe; U+2014 and U+2019 are not. Do not
   widen its use without re-checking coverage. */
@font-face {
  font-family: "Wonderful Snowflake";
  src: url("assets/Wonderful Snowflake.otf") format("opentype");
  font-display: swap;
}

:root {
  --black: #000000;
  --white: #ffffff;
  --gold: #d4af37;
  --dim-gold: #7a6620;
  --dim-white: #888888;
  --dark-grey: #1a1a1a;
  --mid-grey: #333333;
  --red: #c63a3a;
  --green: #4ab85f;
  --amber: #e0a33a;
  --green-fill: #0e2814;
  --amber-fill: #2a1f08;
  --red-fill: #2a0f0f;

  --fire: #e8552d;
  --water: #2d7fe8;
  --earth: #5fb84a;
  --air: #8c7ae8;

  --ui: "Segoe UI", "Helvetica Neue", Ubuntu, "DejaVu Sans", sans-serif;
  --display: "Wonderful Snowflake", var(--ui);
  --mono: Consolas, "DejaVu Sans Mono", monospace;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  background: var(--black);
  color: var(--white);
  font-family: var(--ui);
  font-size: 14px;
  line-height: 1.55;
}

body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 2.25rem 1.25rem 2rem;
}

/* ── brand ───────────────────────────────────────────────────────────────── */

.brand { text-align: center; margin-bottom: 1.75rem; }

/* The artwork is baked white/element-hue-on-transparent by
   updater-gui/tools/make_assets.py — the source art is black on opaque white
   and would be invisible here. Do not swap in the raw source PNGs. */
#elements-logo {
  display: block;
  width: min(320px, 78vw);
  height: auto;
  margin: 0 auto;
}

.subtitle {
  margin: 0.4rem 0 0;
  color: var(--dim-white);
  font-size: 13px;
  font-style: italic;
}

/* ── pages ───────────────────────────────────────────────────────────────── */

main { width: 100%; max-width: 30rem; flex: 1; }

.page { text-align: center; }
.page[hidden] { display: none; }

h2 {
  font-family: var(--display);
  font-weight: 400;
  color: var(--white);
  font-size: 25px;
  letter-spacing: 0.02em;
  margin: 0 0 0.9rem;
}

p { margin: 0 0 0.9rem; }
.dim { color: var(--dim-white); font-size: 13px; }
.quiet { margin-top: 1.4rem; }
.gold { color: var(--gold); }
.warn { color: var(--amber); }

/* Persistent identity of the connected board — ruled off top and bottom so it
   reads as a fact about the hardware rather than as part of whichever page is
   currently showing. */
.board {
  color: var(--dim-white);
  font-size: 13px;
  padding: 7px 0;
  border-top: 1px solid var(--mid-grey);
  border-bottom: 1px solid var(--mid-grey);
  margin-bottom: 1.25rem;
}
.board b { color: var(--white); font-weight: 600; }

code {
  font-family: var(--mono);
  background: var(--dark-grey);
  padding: 0.05em 0.35em;
  border-radius: 2px;
  font-size: 0.92em;
}

a { color: var(--gold); }

/* ── banners ─────────────────────────────────────────────────────────────── */

/* Shape is identical across all three so the colour alone carries the verdict:
   green up-to-date, gold an update exists, amber cannot tell. */
.banner {
  font-size: 16px;
  padding: 10px 14px;
  border-radius: 3px;
  border: 1px solid var(--mid-grey);
  margin: 0 0 1.25rem;
}
.banner.current { color: var(--green); background: var(--green-fill); border-color: var(--green); }
.banner.behind  { color: var(--gold);  background: var(--dark-grey);  border-color: var(--gold); }
.banner.unknown { color: var(--amber); background: var(--amber-fill); border-color: var(--amber); }
.banner.bad     { color: var(--red);   background: var(--red-fill);   border-color: var(--red); }

/* ── buttons ─────────────────────────────────────────────────────────────── */

button { font-family: inherit; cursor: pointer; }

/* The one real action on a page: filled gold, black text, display face. */
.primary {
  background: var(--gold);
  color: var(--black);
  border: 1px solid var(--gold);
  border-radius: 2px;
  font-family: var(--display);
  font-size: 19px;
  padding: 10px 24px;
  transition: background 0.15s;
}
.primary:hover { background: var(--white); border-color: var(--white); }
.primary:disabled {
  background: var(--dim-gold);
  color: var(--dark-grey);
  border-color: var(--dim-gold);
  cursor: default;
}
.primary[hidden] { display: none; }

/* Disclosure links for the expert controls. Text, not buttons: they must not
   compete with the one real action on each page. */
.link {
  background: none;
  border: none;
  color: var(--dim-white);
  text-decoration: underline;
  font-size: 13px;
  padding: 0;
}
.link:hover { color: var(--gold); }

/* ── recovery ────────────────────────────────────────────────────────────── */

.rev-choice {
  display: flex;
  gap: 0.9rem;
  justify-content: center;
  flex-wrap: wrap;
  margin: 1.4rem 0;
}

.rev {
  flex: 1 1 11rem;
  background: transparent;
  border: 1px solid var(--mid-grey);
  border-radius: 2px;
  color: var(--dim-white);
  padding: 1rem 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  transition: border-color 0.15s, color 0.15s;
}
.rev:hover { border-color: var(--gold); color: var(--gold); }
.rev-art  { color: var(--water); font-size: 17px; letter-spacing: 0.05em; }
.rev-name { color: var(--white); font-size: 15px; }
.rev:hover .rev-name { color: var(--gold); }
.rev-sub  { font-size: 12px; letter-spacing: 0.1em; }

/* ── progress ────────────────────────────────────────────────────────────── */

.progress {
  height: 18px;
  background: var(--dark-grey);
  border: 1px solid var(--dim-gold);
  border-radius: 2px;
  overflow: hidden;
  margin: 1.25rem 0;
}
#progress-fill {
  height: 100%;
  width: 0;
  background: var(--gold);
  transition: width 0.2s linear;
}

/* ── result ──────────────────────────────────────────────────────────────── */

.result-title { font-family: var(--display); font-weight: 400; }
.result-title.ok  { color: var(--gold); }
.result-title.bad { color: var(--red); }

/* ── expert drawers + log ────────────────────────────────────────────────── */

.expert, #log-wrap {
  text-align: left;
  margin: 1.4rem auto 0;
  border-top: 1px solid var(--mid-grey);
  padding-top: 0.7rem;
}

summary {
  cursor: pointer;
  color: var(--dim-white);
  font-size: 13px;
  text-decoration: underline;
}
summary:hover { color: var(--gold); }

.expert label { display: block; margin: 0.7rem 0 0.3rem; font-size: 13px; color: var(--dim-white); }
.expert p { margin: 0.7rem 0; }

select, input[type=file] {
  width: 100%;
  background: var(--black);
  color: var(--white);
  border: 1px solid var(--dim-gold);
  border-radius: 2px;
  padding: 4px 8px;
  font-family: inherit;
  font-size: 13px;
}
select:hover, input[type=file]:hover { border-color: var(--gold); }

.notes {
  text-align: left;
  margin-top: 1.5rem;
  border-top: 1px solid var(--mid-grey);
  padding-top: 0.9rem;
  font-size: 13px;
  color: #cccccc;
}
.notes h3 {
  font-family: var(--display);
  color: var(--gold);
  font-size: 20px;
  font-weight: 400;
  margin: 0.9rem 0 0.35rem;
}
.notes ul { margin: 0.3rem 0 0.8rem; padding-left: 1.2rem; }
.notes hr { border: none; border-top: 1px solid var(--mid-grey); margin: 1.1rem 0; }

#log-wrap { width: 100%; max-width: 30rem; }
#log {
  background: var(--dark-grey);
  border: 1px solid var(--mid-grey);
  border-radius: 2px;
  padding: 0.7rem;
  margin: 0.7rem 0 0;
  max-height: 14rem;
  overflow: auto;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.45;
  color: var(--dim-white);
  white-space: pre-wrap;
  word-break: break-word;
}

/* ── maker's stamp ───────────────────────────────────────────────────────── */

.maker {
  text-align: center;
  margin-top: 2.5rem;
  padding-top: 0.5rem;
}
#ev-logo {
  display: block;
  width: min(260px, 62vw);
  height: auto;
  margin: 0 auto;
  padding: 2px;
  opacity: 0.85;
  transition: opacity 0.15s;
}
.maker a:hover #ev-logo { opacity: 1; }
#app-version { margin: 0.25rem 0 0; }

/* ── settings editor ────────────────────────────────────────────────────────
   The updater's pages are one decision each and read fine at 30rem. The editor
   is a form with five sections, so it gets its own width — scoped to the page
   rather than raised globally, or every one-button page would drift apart. */
body[data-page="settings"] main,
body[data-page="settings"] #log-wrap { max-width: 44rem; }

#page-settings { text-align: left; }
#page-settings > .dim { margin: 0 0 1.5rem; }
#settings-board { text-align: center; }

.pref {
  border-top: 1px solid var(--mid-grey);
  padding: 1.25rem 0 0.4rem;
}
.pref h3 {
  font-family: var(--display);
  font-size: 17px;
  font-weight: 400;
  margin: 0 0 0.35rem;
}
.pref > .dim { margin: 0 0 0.8rem; }
.pref .unsupported { color: var(--dim-gold); font-style: italic; }

.pref input[type="text"],
.pref select {
  background: var(--dark-grey);
  color: var(--white);
  border: 1px solid var(--mid-grey);
  border-radius: 3px;
  padding: 0.45rem 0.55rem;
  font-family: var(--ui);
  font-size: 14px;
}
.pref input[type="text"] { width: 100%; max-width: 22rem; }
.pref select { min-width: 14rem; }
.pref input:disabled, .pref select:disabled { color: var(--dim-white); border-color: #262626; }

/* the starting-key choice: the random roll is a real option, so it gets a full
   row and a sentence, not a bare unchecked box */
.choice-rows { display: flex; flex-direction: column; gap: 0.7rem; }
.choice { display: flex; gap: 0.6rem; align-items: flex-start; cursor: pointer; }
.choice-text { display: flex; flex-direction: column; }
.choice-text small { color: var(--dim-white); }
.choice select { margin-top: 0.45rem; }

.tempo-table { display: flex; flex-direction: column; gap: 0.5rem; }
.tempo-row {
  display: flex;
  align-items: flex-end;
  gap: 0.9rem;
  flex-wrap: wrap;
  padding: 0.5rem 0.6rem;
  border: 1px solid transparent;
  border-radius: 3px;
  background: var(--dark-grey);
}
/* The slot this boot selected is the only one an edit can be heard on. */
.tempo-row.active { border-color: var(--dim-gold); }
.tempo-name { min-width: 8.5rem; font-weight: 600; }
.tempo-name em { color: var(--gold); font-weight: 400; font-style: normal; font-size: 12px; }
.tempo-use { display: flex; align-items: center; gap: 0.35rem; color: var(--dim-white); font-size: 13px; }
.tempo-row input[type="number"] {
  width: 5.5rem;
  background: var(--black);
  color: var(--white);
  border: 1px solid var(--mid-grey);
  border-radius: 3px;
  padding: 0.3rem 0.4rem;
  font-family: var(--mono);
}

.field { display: flex; flex-direction: column; gap: 0.2rem; font-size: 12px; color: var(--dim-white); }

.colorset { display: flex; align-items: center; gap: 0.4rem; cursor: pointer; }
.palette-body { margin-top: 0.9rem; transition: opacity 0.15s; }
/* Off is shown, not hidden: an owner who turns their palette off should still
   see what they had, because turning it back on is one click. */
.palette-body.off { opacity: 0.35; pointer-events: none; }

.scale-tabs { display: flex; flex-wrap: wrap; gap: 0.3rem; margin-bottom: 0.9rem; }
.tab {
  background: transparent;
  color: var(--dim-white);
  border: 1px solid var(--mid-grey);
  border-radius: 3px;
  padding: 0.3rem 0.6rem;
  font-family: var(--ui);
  font-size: 12px;
  cursor: pointer;
}
.tab.on { color: var(--black); background: var(--gold); border-color: var(--gold); }

.degree-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
  gap: 0.75rem;
}
.degree {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  padding: 0.55rem;
  background: var(--dark-grey);
  border-radius: 3px;
}
.swatch { height: 2.6rem; border-radius: 2px; border: 1px solid var(--mid-grey); }
.degree-label { font-size: 12px; color: var(--dim-white); }
.degree input[type="range"] { width: 100%; accent-color: var(--gold); }

.settings-actions {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin: 1.6rem 0 0.4rem;
  padding-top: 1.2rem;
  border-top: 1px solid var(--mid-grey);
}
.secondary {
  background: transparent;
  color: var(--white);
  border: 1px solid var(--mid-grey);
  border-radius: 3px;
  padding: 0.6rem 1.1rem;
  font-family: var(--ui);
  font-size: 14px;
  cursor: pointer;
}
.secondary:hover:not(:disabled) { border-color: var(--white); }
.secondary:disabled { color: var(--dim-white); border-color: #262626; cursor: default; }
.dirty { color: var(--amber); font-size: 13px; }
.dirty[hidden] { display: none; }
.quiet.bad { color: var(--red); }

/* ── home: the two doors ────────────────────────────────────────────────────
   The only menu in the app. Both doors always show, each captioned with what is
   behind it — a door that vanishes when it cannot work leaves the page quietly
   smaller than last time with no way to ask why. */
.doors { display: flex; flex-direction: column; gap: 0.8rem; margin-top: 1.6rem; }
.door {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  align-items: flex-start;
  text-align: left;
  padding: 1.1rem 1.25rem;
  background: var(--dark-grey);
  color: var(--white);
  border: 1px solid var(--mid-grey);
  border-radius: 4px;
  cursor: pointer;
  transition: border-color 0.15s;
}
.door:hover:not(:disabled) { border-color: var(--white); }
/* Gold only where there is genuinely something new to install. */
.door.flagged { border-color: var(--gold); }
.door.flagged .door-name { color: var(--gold); }
.door:disabled { cursor: default; opacity: 0.5; }
.door-name { font-family: var(--display); font-size: 19px; }
.door-sub { font-size: 13px; color: var(--dim-white); }

/* ── home: playtime ─────────────────────────────────────────────────────────
   One life measured five ways. Rows are ascending by unit, so the coarsest
   unlocked one sits at the bottom and the readout grows downward as the
   instrument ages.

   Numbers run in the mono face with tabular figures and a fixed min-width so
   the column stays a column when a row gains a digit. The unit labels are
   plain UI font on purpose: Wonderful Snowflake is a display face with 186
   glyphs and no business carrying body copy. */
.playtime {
  margin-top: 2rem;
  padding-top: 1.3rem;
  border-top: 1px solid var(--mid-grey);
}
.playtime-title { font-size: 20px; margin: 0 0 0.7rem; }
.playtime-row {
  display: flex;
  align-items: baseline;
  gap: 0.65rem;
  padding: 0.1rem 0;
}
.playtime-n {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 20px;
  color: var(--white);
  min-width: 6ch;
  text-align: right;
}
.playtime-u { color: var(--dim-white); font-size: 13px; }
/* The one case where an absence is named rather than hidden: firmware with no
   journal at all, sitting directly under the update door. */
.playtime-none { color: var(--dim-white); font-size: 13px; margin: 0; }

/* ── result: what the version actually became ───────────────────────────────
   The before -> after pair is the proof the update landed. A success screen
   with no version on it asks the owner to take the word of the thing under
   test. The warning row fires when the board reports something other than what
   was installed -- silent otherwise, and the only symptom would be a version
   that never moves. */
.result-versions { margin: 0 0 1rem; }
.result-vrow {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 0.55rem;
  font-family: var(--mono);
  font-size: 15px;
  color: var(--dim-white);
}
.result-vrow b { color: var(--white); font-weight: 600; }
.result-varrow { color: var(--dim-gold); }
.result-vwarn {
  margin-top: 0.6rem;
  color: var(--amber);
  font-size: 13px;
  line-height: 1.45;
}
.result-vwarn b { color: var(--amber); font-weight: 600; }

/* ── the disconnect control on the board line ───────────────────────────────
   Floated right so the three callers that append their own trailer to
   boardLine() cannot push it around. Quiet by default: letting go of the board
   is a thing you occasionally need, never the thing the page is for -- so it
   reads as a link until hovered, and only then admits to being a button. */
.board-disconnect {
  float: right;
  background: none;
  border: 1px solid transparent;
  color: var(--dim-white);
  font-family: var(--ui);
  font-size: 12px;
  padding: 1px 8px;
  margin-left: 0.75rem;
  border-radius: 3px;
  cursor: pointer;
}
.board-disconnect:hover {
  color: var(--white);
  border-color: var(--mid-grey);
}

/* ── language switch, in the footer ─────────────────────────────────────────
   Beside the version rather than on the settings page: settings needs a
   connected board, so a reader who could not understand the waiting page would
   find the switch behind a door they cannot open. Deliberately small -- it is
   set once and then never touched again. */
.lang-switch { display: flex; gap: 0.35rem; justify-content: center; margin-top: 0.4rem; }
.lang-opt {
  background: none;
  border: 1px solid transparent;
  color: var(--dim-white);
  font-family: var(--ui);
  font-size: 11px;
  padding: 1px 7px;
  border-radius: 3px;
  cursor: pointer;
}
.lang-opt:hover { color: var(--white); border-color: var(--mid-grey); }
.lang-opt.on { color: var(--gold); border-color: var(--dim-gold); cursor: default; }
