/*
 * Base stylesheet for the visual-novel engine.
 *
 * The STRUCTURE below (title screen, plate frame, text box, choices, minigame
 * canvas, ending card, reset control) is the reusable part — it matches the
 * DOM in index.html and the states engine.js drives. Leave the selectors and
 * layout alone unless you're changing the actual UI shape.
 *
 * Everything under "PROJECT PALETTE" and "SPEAKER REGISTERS" below is *not*
 * generic — es ist die Style Bible aus design-catalog.md §2 als CSS.
 * Verdrahtet sind die drei benannten Sprecher hedda / stimme / bertrun.
 * `data-speaker="none"` is reserved for the narrator/caption register (see
 * docs/03-WRITING-VOICE.md) and needs no per-project id.
 */

:root {
  /* ─── PROJECT PALETTE — replace with your locked, hex-pinned style bible ───
     Keep it small and keep every non-neutral color assigned to exactly ONE
     semantic role (see docs/02-IMAGE-CONSISTENCY.md, "palette discipline").
     These placeholders are a neutral grayscale so the template runs unstyled
     out of the box; they are not a design suggestion. */
  /* Aus design-catalog.md §2, wörtlich. Die Rampe läuft von Knochenweiß nach
     warmem Fastschwarz; die Zwischenstufen sind die gemessenen Massefarben
     der Referenzbilder, nicht erfunden. */
  --paper-hi:   #EDEBD8;  /* Knochenweiß, leicht angehoben */
  --paper:      #E1DEC6;  /* Knochenweiß — Massefarbe beider Referenzen */
  --paper-lo:   #CBC7AC;
  --drab-lt:    #BDBD79;  /* blasses Oliv */
  --grey-mid:   #93A6B2;  /* blasses Schiefer */
  --drab:       #6B6049;  /* Khaki */
  --slate:      #5D6E80;  /* Schieferblau */
  --shadow:     #423F43;  /* dunkles Blaugrau */
  --deep:       #412F29;  /* Dunkelbraun */
  --mass:       #241C16;
  --ink:        #1B120E;  /* warmes Fastschwarz */

  /* Je eine Rolle, wie in §2 festgelegt. Die -deep-Varianten sind dieselbe
     Farbe, für Text auf hellem Grund abgedunkelt — die Rolle ändert sich
     dadurch nicht. */
  --accent-a:      #ED8A4C;  /* Glutorange: lebendiges Feuer und Tageslicht. Bertrun. */
  --accent-a-deep: #A85A22;
  --accent-b:      #5E9E92;  /* Archivcyan: Licht der Alten Welt. Die Stimme. */
  --accent-b-deep: #35635B;

  --font-a: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;
  --font-b: Georgia, "Iowan Old Style", "Palatino Linotype", Palatino, serif;

  --measure: 68ch;
}

* { box-sizing: border-box; }

/* An ID selector outranks the UA stylesheet's `[hidden] { display: none }`, so
   #minigame/#choices would paint even while hidden. Keep this above them. */
[hidden] { display: none !important; }

html, body {
  height: 100%;
  margin: 0;
}

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-b);
  display: grid;
  place-items: center;
  padding: clamp(0.75rem, 2vw, 2rem);
  /* Optional paper-grain texture, inline SVG, no external asset. Drop it if
     your style bible isn't paper-and-ink. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='0.06'/%3E%3C/svg%3E");
}

#app {
  width: min(105ch, 100%);
  display: flex;
  flex-direction: column;
  gap: clamp(0.75rem, 1.5vw, 1.25rem);
}

/* ─── Title ─────────────────────────────────────────────────────────────── */

#title {
  width: min(105ch, 100%);
  aspect-ratio: 3 / 2;  /* match this to your plate model's native output ratio, see docs/02 */
  position: relative;
  border: 1px solid var(--ink);
  outline: 1px solid var(--ink);
  outline-offset: 3px;
  overflow: hidden;
  background-color: var(--paper-lo);
  background-image:
    linear-gradient(
      100deg,
      color-mix(in srgb, var(--paper) 94%, transparent) 0 34%,
      color-mix(in srgb, var(--paper) 70%, transparent) 46%,
      color-mix(in srgb, var(--paper) 8%, transparent) 68%
    ),
    url("../assets/plates/plate_title.png");
  background-size: cover, cover;
  background-position: center, center;
  display: flex;
  align-items: center;
}

#title-card {
  padding: clamp(1.25rem, 4vw, 3.25rem);
  max-width: 46ch;
}

.title-kicker {
  font-family: var(--font-a);
  font-size: 0.64rem;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--drab);
  margin: 0 0 0.5rem;
}

#title h1 {
  font-family: var(--font-a);
  font-weight: 400;
  /* Einwortiger Titel: er darf groß sein und trägt den Bildschirm. Die Größe
     war vorher auf einen Fünfwörter-Titel heruntergeregelt — beim Umbenennen
     mitzuziehen, sonst steht das Wort verloren in der Karte. */
  font-size: clamp(2.4rem, 7vw, 4.8rem);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink);
  margin: 0 0 0.1em;
  line-height: 1;
  text-wrap: balance;
}

.title-sub {
  font-family: var(--font-a);
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  color: var(--slate);
  margin: 0.7rem 0 1.5rem;
}

#title-status {
  margin: 0 0 1.75rem;
  border-top: 1px solid var(--drab-lt);
  font-family: var(--font-a);
  font-size: 0.66rem;
  letter-spacing: 0.08em;
}
#title-status > div {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.38rem 0;
  border-bottom: 1px solid var(--drab-lt);
}
#title-status dt { color: var(--drab); text-transform: uppercase; }
#title-status dd {
  margin: 0;
  color: var(--slate);
  text-transform: uppercase;
}
/* Let the last status row carry weight if it's your hook line (SEKTOR-7 used
   this for "Occupancy: zero" — the line the story's first turn answers). */
#title-status > div:last-child dt,
#title-status > div:last-child dd { color: var(--ink); }

#title-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.55rem;
}

#title-actions button {
  font-family: var(--font-a);
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
  background: var(--paper-hi);
  border: 1px solid var(--ink);
  padding: 0.72rem 1.3rem;
  cursor: pointer;
  transition: background 100ms linear, box-shadow 100ms linear;
}
#title-actions button:hover,
#title-actions button:focus-visible {
  background: var(--paper-lo);
  outline: none;
  box-shadow: inset 3px 0 0 var(--accent-a);
}
#title-actions #start { border-color: var(--slate); color: var(--slate); }

@media (max-width: 560px) {
  #title {
    aspect-ratio: auto;
    min-height: 30rem;
    background-image:
      linear-gradient(
        180deg,
        color-mix(in srgb, var(--paper) 92%, transparent) 0 62%,
        color-mix(in srgb, var(--paper) 30%, transparent) 100%
      ),
      url("../assets/plates/plate_title.png");
    background-position: center, center bottom;
  }
  #title-card { max-width: none; }
}

/* ─── The plate ─────────────────────────────────────────────────────────── */

#plate {
  position: relative;
  margin: 0;
  /* MEASURE THIS — do not assume 16:9. Ask your model for one ratio and it
     may well return another: gpt-image-2 asked for 16:9 returned 1536x1024
     (3:2) every single time. Set this to what actually comes back, because
     `object-fit: cover` on a mismatched ratio silently crops every plate —
     and it crops the top and bottom, which is where sky, floor and a
     first-person character's own hands live. See
     docs/02-IMAGE-CONSISTENCY.md, "practical gotchas". */
  aspect-ratio: 3 / 2;   /* gemessen: gpt-image-2 liefert 1536x1024 = 3:2 */
  background: var(--paper-lo);
  border: 1px solid var(--ink);
  outline: 1px solid var(--ink);
  outline-offset: 3px;
  overflow: hidden;
}

#plate-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
#plate-img:not([src]), #plate-img[src=""] { display: none; }

#plate-placeholder {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 0.6rem;
  font-family: var(--font-a);
  background:
    repeating-linear-gradient(
      45deg,
      transparent 0 11px,
      color-mix(in srgb, var(--drab-lt) 55%, transparent) 11px 12px
    );
}

.ph-label {
  font-size: 0.7rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--drab);
}

.ph-id {
  font-size: clamp(0.85rem, 2vw, 1.15rem);
  letter-spacing: 0.06em;
  color: var(--slate);
  border: 1px dashed var(--grey-mid);
  background: var(--paper);
  padding: 0.45rem 0.9rem;
}

#plate-caption {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  font-family: var(--font-a);
  font-size: 0.62rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--drab);
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  border-top: 1px solid var(--drab-lt);
  padding: 0.3rem 0.6rem;
  justify-content: space-between;

  /* engine.js writes the raw plate id into this strip. Useful scaffolding
     while building — you can see at a glance which asset a node points at.
     Set to `none` before shipping: a caption reading PLATE_FOO_BAR across the
     bottom of your artwork is dev furniture. */
  display: flex;
}

/* ─── The text box ──────────────────────────────────────────────────────── */

#box {
  border: 1px solid var(--ink);
  background: var(--paper-hi);
  padding: clamp(0.9rem, 2vw, 1.4rem);
  min-height: 8.5rem;
  position: relative;
  cursor: pointer;
}

#speaker {
  font-family: var(--font-a);
  font-size: 0.64rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--accent-a);
  margin-bottom: 0.55rem;
  min-height: 0.9rem;
}
/* A speaker with no visual label (e.g. an omnipresent/environmental voice) —
   see engine.js SPEAKER_LABEL. Delete this rule if every speaker gets a label. */
#box[data-speaker="none"] #speaker { visibility: hidden; }

#text {
  margin: 0;
  max-width: var(--measure);
  font-size: clamp(1rem, 1.15vw + 0.72rem, 1.2rem);
  line-height: 1.65;
  white-space: pre-wrap;
}

/* ── Sprecher-Register — ein optisches Register je Stimme, docs/03. ──
   Man soll sehen, wer spricht, bevor man ein Wort gelesen hat; das Label ist
   die Bestätigung, nicht das Signal. */

/* Hedda — die menschliche Mitte: Serife, voller Kontrast, ruhig. */
#box[data-speaker="hedda"] #text {
  font-family: var(--font-b);
  color: var(--ink);
}
#box[data-speaker="hedda"] #speaker { color: var(--deep); }

/* Die Stimme — eine Konserve: Schreibmaschinenbreite, gesperrt, Archivcyan.
   Nichts an ihr ist warm. */
#box[data-speaker="stimme"] #text {
  font-family: var(--font-a);
  color: var(--accent-b-deep);
  font-size: clamp(0.92rem, 1vw + 0.66rem, 1.06rem);
  letter-spacing: 0.02em;
  line-height: 1.75;
}
#box[data-speaker="stimme"] #speaker { color: var(--accent-b-deep); }

/* Bertrun — Glut: Serife, halbfett, kurze Sätze, warm. */
#box[data-speaker="bertrun"] #text {
  font-family: var(--font-b);
  color: var(--accent-a-deep);
  font-weight: 600;
}
#box[data-speaker="bertrun"] #speaker { color: var(--accent-a-deep); }

/* Narrator / caption register (speaker: null in story.js) — third person,
   present tense, spare. See docs/03-WRITING-VOICE.md. */
#box[data-speaker="none"] #text {
  font-style: italic;
  color: var(--slate);
}

#advance {
  position: absolute;
  right: 0.9rem;
  bottom: 0.7rem;
  width: 0.5rem;
  height: 0.5rem;
  background: var(--ink);
  opacity: 0;
  transition: opacity 120ms linear;
}
#box[data-done="true"] #advance {
  opacity: 1;
  animation: blink 1.1s steps(1, end) infinite;
}
@keyframes blink { 50% { opacity: 0.15; } }

/* ─── Choices ───────────────────────────────────────────────────────────── */

#choices {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

#choices button {
  font-family: var(--font-a);
  font-size: clamp(0.8rem, 0.75vw + 0.62rem, 0.92rem);
  line-height: 1.55;
  text-align: left;
  color: var(--ink);
  background: var(--paper-hi);
  border: 1px solid var(--slate);
  padding: 0.75rem 0.95rem;
  cursor: pointer;
  transition: background 100ms linear, border-color 100ms linear;
}

#choices button:hover,
#choices button:focus-visible {
  background: var(--paper-lo);
  border-color: var(--ink);
  outline: none;
  box-shadow: inset 3px 0 0 var(--accent-a);
}

/* ─── Minigame ──────────────────────────────────────────────────────────── */

#minigame {
  width: 100%;
  aspect-ratio: 16 / 7;
  border: 1px solid var(--ink);
  background: var(--paper-hi);
  display: block;
  cursor: pointer;
  margin-bottom: 2.5rem;  /* keep the canvas off the page edge */
}

/* ─── Ending ────────────────────────────────────────────────────────────── */

#ending {
  border: 1px solid var(--ink);
  outline: 1px solid var(--ink);
  outline-offset: 3px;
  background: var(--paper-hi);
  padding: clamp(1.5rem, 4vw, 2.75rem);
  text-align: center;
}

.ending-kicker {
  font-family: var(--font-a);
  font-size: 0.64rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--drab);
}

#ending h1 {
  font-family: var(--font-a);
  font-size: clamp(1.4rem, 4vw, 2.1rem);
  font-weight: 400;
  letter-spacing: 0.3em;
  margin: 0.75rem 0 1.75rem;
  color: var(--ink);
}

#ending button, #reset, #back {
  font-family: var(--font-a);
  font-size: 0.7rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--drab);
  background: transparent;
  border: 1px solid var(--drab-lt);
  padding: 0.5rem 1rem;
  cursor: pointer;
}
#ending button:hover, #reset:hover, #back:hover {
  color: var(--ink);
  border-color: var(--ink);
}

/* Two-step confirm affordance — see engine.js resetArm(). A stray click costs
   a full playthrough, so the destructive state must look different. */
/* Playtest-Hilfe. Sie verändert das Spiel: wer zurückgehen kann, kann eine
   Entscheidung zurücknehmen. Zum Ausliefern genügt `display: none`. */
#back {
  position: fixed;
  right: 11.5rem;
  bottom: 1rem;
  background: var(--paper-hi);
  border-color: var(--grey-mid);
  color: var(--slate);
  opacity: 0.75;
  transition: opacity 120ms linear, color 120ms linear, border-color 120ms linear;
}
#back:hover, #back:focus-visible {
  opacity: 1;
  color: var(--ink);
  border-color: var(--slate);
}
#back[disabled] { opacity: 0.28; cursor: default; }

#reset {
  position: fixed;
  right: 1rem;
  bottom: 1rem;
  background: var(--paper-hi);
  border-color: var(--grey-mid);
  color: var(--slate);
  opacity: 0.75;
  transition: opacity 120ms linear, color 120ms linear, border-color 120ms linear;
}
#reset:hover, #reset:focus-visible {
  opacity: 1;
  color: var(--ink);
  border-color: var(--ink);
  outline: none;
}
#reset[data-armed="true"] {
  opacity: 1;
  color: var(--accent-a);
  border-color: var(--accent-a);
  box-shadow: inset 2px 0 0 var(--accent-a);
}

@media (prefers-reduced-motion: reduce) {
  #box[data-done="true"] #advance { animation: none; }
}

/* ─── Ausliefern (scripts/deploy.sh, nicht von Hand pflegen) ─────────────── */
/* Plattenkennung über der Grafik: Gerüst fürs Begutachten, nicht fürs Spiel. */
#plate-caption { display: none; }
/* Der Zurück-Schritt ist eine Playtest-Hilfe — er nimmt Entscheidungen
   zurück. Weg damit; engine.js schaltet mit dem Knopf auch die Rücktaste ab. */
#back { display: none; }
