/* ═══════════════════════════════════════════════════════════════
   IMAHE — "The Living Comic Panel" design system
   Paper-and-ink light base • riso accents • halftone • hard shadows
   Fonts: Bangers (action) · Fredoka (UI) · Nunito Sans (body) · Space Mono (numbers)
   ═══════════════════════════════════════════════════════════════ */

:root {
  --paper: #F7F1E1;
  --paper-2: #FBF6E9;
  --paper-sunk: #EFE7D0;
  --halftone: #E9DFC4;
  --ink: #1A1712;
  --ink-soft: #3A342B;
  --ink-line: #241F18;
  --newsprint-mute: #8A8069;
  --panel-shadow: rgba(26, 23, 18, 0.18);

  --riso-pink: #FF4D6D;
  --riso-pink-ink: #C42847;
  --riso-pink-2: #FF7A93;
  --riso-blue: #3D5AFE;
  --riso-blue-2: #6E82FF;
  --riso-yellow: #FFC531;
  --riso-yellow-deep: #F0A500;
  --riso-teal: #12B5A5;
  --riso-purple: #7A3DFF;

  --speech-fill: #FFFFFF;
  --speech-stroke: #1A1712;
  --success: #12B5A5;
  --success-ink: #0A7A6F;
  --warning: #F0A500;
  --danger: #FF4D6D;
  --danger-ink: #C42847;
  --locked: #B9AF96;
  --locked-hatch: #CFC6AE;
  --credit-gold: #FFC531;
  --credit-gold-deep: #E09B00;
  --focus-ring: #3D5AFE;
  --overlay-scrim: rgba(26, 23, 18, 0.72);

  --f-display: 'Bangers', cursive;
  --f-head: 'Fredoka', sans-serif;
  --f-body: 'Nunito Sans', sans-serif;
  --f-mono: 'Space Mono', monospace;

  --shadow-hard: 3px 3px 0 var(--panel-shadow);
  --shadow-harder: 4px 4px 0 var(--ink);
  --border-ink: 2.5px solid var(--ink-line);
  --radius: 14px;
  --radius-lg: 20px;

  --masthead-h: 52px;
  --tabbar-h: 68px;
  --safe-b: env(safe-area-inset-bottom, 0px);
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html { height: 100%; }
body {
  margin: 0; min-height: 100%;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--f-body);
  font-size: 16px; line-height: 1.5;
  overflow-x: hidden;
  /* app-wide faint halftone print texture */
  background-image: radial-gradient(var(--halftone) 1px, transparent 1.2px);
  background-size: 9px 9px;
}

h1, h2, h3 { font-family: var(--f-head); margin: 0; }
.bangers { font-family: var(--f-display); letter-spacing: 0.02em; line-height: 0.95; }
.mono { font-family: var(--f-mono); }

button { font-family: var(--f-head); cursor: pointer; }
input, textarea, select { font-family: var(--f-body); font-size: 16px; color: var(--ink); }
a { color: var(--riso-blue); }
.hidden { display: none !important; }
img { max-width: 100%; display: block; }

:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 2px; border-radius: 4px; }

/* ─── Layout shell ─── */
.app { min-height: 100vh; display: flex; }
.app-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.view {
  flex: 1;
  padding: 14px 14px calc(var(--tabbar-h) + var(--safe-b) + 34px);
  max-width: 640px; width: 100%; margin: 0 auto;
}

/* ─── Masthead ─── */
.masthead {
  position: sticky; top: 0; z-index: 40;
  height: var(--masthead-h);
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 14px;
  background: var(--paper-2);
  border-bottom: var(--border-ink);
  /* torn paper bottom edge */
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - 4px), 96% 100%, 91% calc(100% - 3px), 85% 100%, 79% calc(100% - 4px), 72% 100%, 65% calc(100% - 2px), 58% 100%, 50% calc(100% - 4px), 43% 100%, 36% calc(100% - 3px), 29% 100%, 22% calc(100% - 4px), 15% 100%, 9% calc(100% - 2px), 4% 100%, 0 calc(100% - 4px));
}
.masthead .wordmark {
  font-family: var(--f-display); font-size: 26px; text-decoration: none; color: var(--ink);
  position: relative; padding-bottom: 2px;
}
.masthead .wordmark::after {
  content: ''; position: absolute; left: 0; right: 6px; bottom: 0; height: 5px;
  background-image: radial-gradient(var(--riso-pink) 1.2px, transparent 1.4px);
  background-size: 6px 6px;
}
.masthead .m-actions { display: flex; align-items: center; gap: 8px; }

/* credit coin pill */
.coin-pill {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--speech-fill); border: 2px solid var(--ink-line);
  border-radius: 999px; padding: 4px 12px 4px 6px;
  font-family: var(--f-mono); font-weight: 700; font-size: 14px;
  box-shadow: 2px 2px 0 var(--panel-shadow);
  text-decoration: none; color: var(--ink);
}
.coin-pill .coin {
  width: 20px; height: 20px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #FFE08A, var(--credit-gold) 55%, var(--credit-gold-deep));
  border: 2px solid var(--ink-line);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 10px; font-weight: 800;
}
.coin-pill.is-low { border-color: var(--danger-ink); color: var(--danger-ink); animation: shake 0.35s; }

/* ─── Comic panel card ─── */
.panel {
  background: var(--paper-2);
  border: var(--border-ink);
  border-radius: var(--radius);
  box-shadow: var(--shadow-hard);
  padding: 16px;
  position: relative;
}
.panel--tilt-l { transform: rotate(-1deg); }
.panel--tilt-r { transform: rotate(1deg); }
.panel--tilt-l:focus-within, .panel--tilt-r:focus-within,
.panel--tilt-l:active, .panel--tilt-r:active { transform: rotate(0); transition: transform 0.18s ease-out; }
.panel-title {
  font-family: var(--f-head); font-weight: 700; font-size: 13px;
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-soft);
  display: flex; align-items: center; gap: 8px; margin-bottom: 10px;
}

/* halftone texture helper */
.halftone-bg {
  background-image: radial-gradient(var(--halftone) 1.4px, transparent 1.6px);
  background-size: 8px 8px;
}

/* ─── Speech-bubble button ─── */
.bubble-btn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  background: var(--riso-pink); color: #fff;
  font-family: var(--f-display); font-size: 20px; letter-spacing: 0.04em;
  border: var(--border-ink); border-radius: 16px;
  padding: 12px 26px;
  box-shadow: var(--shadow-harder);
  transition: transform 0.08s, box-shadow 0.08s;
  text-decoration: none;
}
.bubble-btn::after { /* bubble tail */
  content: ''; position: absolute; bottom: -10px; left: 22px;
  width: 14px; height: 14px; background: inherit;
  border-right: var(--border-ink); border-bottom: var(--border-ink);
  transform: skewX(-18deg) rotate(45deg);
  border-radius: 0 0 4px 0;
}
.bubble-btn:active { transform: translate(4px, 4px); box-shadow: 0 0 0 var(--ink); }
.bubble-btn:disabled { background: var(--locked); color: var(--paper-2); cursor: not-allowed; box-shadow: var(--shadow-hard); }
.bubble-btn:disabled::after { border-color: var(--ink-line); }
.bubble-btn--blue { background: var(--riso-blue); }
.bubble-btn--teal { background: var(--riso-teal); }
.bubble-btn--yellow { background: var(--riso-yellow); color: var(--ink); }
.bubble-btn--ghost { background: var(--speech-fill); color: var(--ink); }
.bubble-btn--sm { font-size: 16px; padding: 8px 18px; border-radius: 12px; }
.bubble-btn--block { width: 100%; }

/* plain chip */
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--speech-fill); color: var(--ink);
  font-family: var(--f-head); font-weight: 600; font-size: 13px;
  border: 2px solid var(--ink-line); border-radius: 999px;
  padding: 6px 14px;
  box-shadow: 2px 2px 0 var(--panel-shadow);
  transition: transform 0.08s, box-shadow 0.08s;
}
.chip:active { transform: translate(2px, 2px); box-shadow: 0 0 0 var(--panel-shadow); }
.chip.is-on { background: var(--ink); color: var(--paper); }
/* price rider on a chip that spends credits — dimmer than the label so the
   action stays the thing you read first */
.chip-cost { font-size: 11px; font-weight: 700; opacity: 0.65; }
.chip-cost:empty { display: none; }
.chip--pink.is-on { background: var(--riso-pink); color: #fff; }
.chip--blue.is-on { background: var(--riso-blue); color: #fff; }

/* ─── Ink inputs ─── */
.ink-field { display: flex; flex-direction: column; gap: 5px; }
.ink-label {
  font-family: var(--f-head); font-weight: 600; font-size: 11px;
  text-transform: uppercase; letter-spacing: 0.1em; color: var(--newsprint-mute);
}
.ink-input, .ink-area {
  background: transparent; border: none;
  border-bottom: 2px solid var(--ink-line);
  padding: 8px 2px; outline: none;
  transition: border-color 0.15s, border-width 0.15s;
}
.ink-input:focus, .ink-area:focus { border-bottom: 3px solid var(--riso-blue); }
.ink-area {
  background: var(--speech-fill);
  border: 2px solid var(--ink-line); border-radius: var(--radius);
  padding: 12px; min-height: 90px; resize: vertical;
  box-shadow: 2px 2px 0 var(--panel-shadow);
}
.ink-area:focus { border: 2px solid var(--riso-blue); }

/* Ink dropdown — a real <select>, so phones get their native picker wheel
   instead of a hand-rolled menu that fights the keyboard. */
.ink-select {
  width: 100%;
  background: var(--speech-fill);
  border: 2px solid var(--ink-line); border-radius: var(--radius);
  box-shadow: 2px 2px 0 var(--panel-shadow);
  padding: 11px 34px 11px 12px;
  font-family: var(--f-head); font-weight: 600; font-size: 15px;
  color: var(--ink);
  appearance: none; -webkit-appearance: none;
  /* chevron, drawn so no image request is needed */
  background-image:
    linear-gradient(45deg, transparent 50%, var(--ink) 50%),
    linear-gradient(135deg, var(--ink) 50%, transparent 50%);
  background-position: right 16px center, right 11px center;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
  cursor: pointer;
}
.ink-select:focus { outline: none; border-color: var(--riso-blue); }
.ink-select optgroup { font-family: var(--f-head); font-style: normal; }

/* ─── Dropzone ─── */
.dropzone {
  border: 2.5px dashed var(--ink-line); border-radius: var(--radius);
  background: var(--speech-fill);
  min-height: 96px; padding: 14px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
  text-align: center; cursor: pointer; position: relative;
  transition: background 0.15s, border-color 0.15s;
}
.dropzone:hover, .dropzone.drag-over { background: var(--paper-sunk); border-color: var(--riso-blue); }
.dropzone input[type="file"] { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
.dropzone .dz-hint { font-family: var(--f-head); font-weight: 600; font-size: 13px; color: var(--newsprint-mute); }
.dz-thumbs { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; align-items: flex-start; }
/* .dz-thumb is just the column wrapper; .dz-pic carries the ink frame so a
   name box can sit underneath without inheriting the border or the crop. */
.dz-thumb { position: relative; display: flex; flex-direction: column; gap: 4px; }
.dz-pic {
  width: 64px; height: 64px; border: 2px solid var(--ink-line); border-radius: 10px;
  overflow: hidden; position: relative; background: var(--paper-sunk);
}
.dz-pic img { width: 100%; height: 100%; object-fit: cover; }
.dz-pic .dz-x {
  position: absolute; top: 2px; right: 2px;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--ink); color: var(--paper); border: none;
  font-size: 10px; line-height: 1; display: flex; align-items: center; justify-content: center;
}

/* named references (character casting) */
.dz-thumb--named .dz-pic { width: 78px; height: 78px; }
.dz-name {
  width: 78px; padding: 3px 6px;
  background: var(--speech-fill);
  border: 2px solid var(--ink-line); border-radius: 8px;
  font-family: var(--f-head); font-weight: 600; font-size: 11px;
  text-align: center; color: var(--ink);
  box-shadow: 1px 1px 0 var(--panel-shadow);
}
.dz-name::placeholder { color: var(--newsprint-mute); font-weight: 500; }
.dz-name:focus { outline: none; border-color: var(--riso-blue); }

/* ─── Bottom tab bar (mobile) ─── */
.tabbar {
  position: fixed; left: 12px; right: 12px;
  bottom: calc(var(--safe-b) + 12px);
  height: var(--tabbar-h); z-index: 50;
  background: var(--paper-2);
  border: var(--border-ink); border-radius: 18px;
  box-shadow: var(--shadow-harder);
  display: flex; align-items: stretch; justify-content: space-around;
}
.tabbar .tab {
  flex: 1; border: none; background: transparent;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  color: var(--newsprint-mute); font-family: var(--f-head); font-weight: 600; font-size: 10px;
  text-decoration: none; border-radius: 14px;
}
.tabbar .tab svg { width: 24px; height: 24px; }
.tabbar .tab.is-active { color: var(--ink); }
.tabbar .tab.is-active svg { filter: drop-shadow(2px 2px 0 var(--riso-yellow)); }
.tabbar .tab-fab-space { flex: 0 0 72px; }
/* No FAB on this route — collapse its reserved slot so the tabs close up
   instead of leaving a gap where the button would have been. */
.tabbar.no-fab .tab-fab-space { display: none; }

/* FAB — the MAKE! button, and it sits IN the tab row rather than on top of it.
   Both the button and the bar carry a heavy ink border; raised above the bar
   those two borders merged into one lumpy shape and the button read as
   sinking into the tabs. Centred inside the bar it lines up with the other
   four buttons, which is what it always looked like it was failing to do.
   (68px bar - 56px button) / 2 = 6px of breathing room top and bottom. */
.fab {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(var(--safe-b) + 12px + 6px);
  z-index: 51;
  width: 56px; height: 56px; border-radius: 18px;
  background: var(--riso-pink); color: #fff;
  border: var(--border-ink); box-shadow: var(--shadow-harder);
  display: flex; align-items: center; justify-content: center;
  font-size: 0;   /* the glyph is drawn below, not typeset */
  transition: transform 0.1s;
}
/* The "+" is drawn, not lettered. As a Bangers glyph on line-height:1 it sat
   visibly high and left of centre — display faces carry asymmetric side
   bearings and internal leading, so "centre the text" does not centre the ink.
   Two bars centred in the box always land dead centre. */
.fab::after {
  content: ''; display: block;
  width: 24px; height: 24px;
  background:
    linear-gradient(currentColor, currentColor) center / 24px 5px no-repeat,
    linear-gradient(currentColor, currentColor) center / 5px 24px no-repeat;
}
/* Centred above the button, not hung off one corner — the old top/right offset
   pushed the whole cluster's visual weight to the right of a button that was
   mathematically centred all along. */
.fab::before {
  content: 'MAKE!'; position: absolute; top: -12px; left: 50%;
  background: var(--riso-yellow); color: var(--ink);
  font-family: var(--f-display); font-size: 11px; line-height: 1.4;
  padding: 1px 8px; border: 2px solid var(--ink-line); border-radius: 8px;
  white-space: nowrap;
  transform: translateX(-50%) rotate(-5deg);
}
.fab:active { transform: translateX(-50%) scale(0.92); }

/* create sheet (FAB burst) */
.create-sheet {
  position: fixed; inset: 0; z-index: 60;
  background: var(--overlay-scrim);
  display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
  padding: 0 18px calc(var(--safe-b) + 110px); gap: 14px;
}
.create-sheet .cs-title {
  font-family: var(--f-display); color: var(--paper); font-size: 24px;
  text-shadow: 2px 2px 0 var(--ink);
}
.create-sheet .cs-card {
  width: 100%; max-width: 420px;
  display: flex; align-items: center; gap: 14px;
  background: var(--paper-2); border: var(--border-ink); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-harder); padding: 16px 18px;
  font-family: var(--f-head); font-weight: 700; font-size: 18px; color: var(--ink);
  text-decoration: none;
  animation: pop-up 0.28s cubic-bezier(0.2, 1.4, 0.4, 1) both;
}
.create-sheet .cs-card:nth-child(3) { animation-delay: 0.06s; }
.create-sheet .cs-card .cs-emoji { font-size: 30px; }
.create-sheet .cs-card small { display: block; font-weight: 500; font-size: 12px; color: var(--newsprint-mute); }

/* ─── Desktop spine rail ─── */
.spine { display: none; }

/* ─── POW toast ─── */
.toast-layer {
  position: fixed; top: 14px; left: 0; right: 0; z-index: 100;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  pointer-events: none;
}
.pow-toast {
  --pow-bg: var(--riso-yellow);
  position: relative;
  background: var(--pow-bg); color: var(--ink);
  font-family: var(--f-display); font-size: 20px;
  padding: 10px 22px;
  border: var(--border-ink);
  clip-path: polygon(4% 12%, 12% 4%, 22% 10%, 32% 0%, 40% 9%, 52% 2%, 60% 11%, 72% 3%, 79% 12%, 92% 7%, 96% 20%, 100% 32%, 93% 42%, 99% 55%, 92% 64%, 98% 76%, 88% 84%, 93% 96%, 79% 92%, 68% 99%, 60% 90%, 48% 98%, 40% 89%, 28% 97%, 22% 87%, 10% 93%, 8% 80%, 0% 72%, 6% 60%, 0% 48%, 7% 38%, 2% 26%);
  animation: pow 0.32s cubic-bezier(0.2, 1.4, 0.4, 1) both;
  pointer-events: auto;
}
.pow-toast--ok { --pow-bg: var(--riso-teal); color: #fff; }
.pow-toast--err { --pow-bg: var(--riso-pink); color: #fff; }
.pow-toast.is-leaving { animation: pow-out 0.25s ease-in both; }

/* speech bubble (mascot speech, info) */
.speech {
  position: relative; background: var(--speech-fill);
  border: var(--border-ink); border-radius: 16px;
  padding: 10px 14px; font-family: var(--f-head); font-weight: 600;
  box-shadow: 2px 2px 0 var(--panel-shadow);
}
.speech::after {
  content: ''; position: absolute; bottom: -9px; left: 26px;
  width: 12px; height: 12px; background: var(--speech-fill);
  border-right: var(--border-ink); border-bottom: var(--border-ink);
  transform: rotate(45deg);
}

/* ─── Inky mascot ─── */
.inky { display: inline-block; animation: inky-bob 2.4s ease-in-out infinite; transform-origin: 50% 90%; }
.inky.inky--pop { animation: inky-pop 0.4s cubic-bezier(0.2, 1.6, 0.4, 1); }
.inky.inky--sleep .inky-eye { transform: scaleY(0.12); transform-origin: center; }

/* ─── SOON / locked card ─── */
.soon-card {
  position: relative; overflow: hidden;
  background: repeating-linear-gradient(45deg, var(--paper-sunk), var(--paper-sunk) 6px, var(--locked-hatch) 6px, var(--locked-hatch) 10px);
  border: 2.5px solid var(--locked);
  border-radius: var(--radius); padding: 16px;
  color: var(--newsprint-mute);
  filter: saturate(0.4);
}
.soon-card .soon-ribbon {
  position: absolute; top: 12px; right: -34px;
  background: var(--riso-pink); color: #fff;
  font-family: var(--f-display); font-size: 15px; letter-spacing: 0.08em;
  padding: 4px 40px; transform: rotate(35deg);
  border-top: 2px solid var(--ink-line); border-bottom: 2px solid var(--ink-line);
}
.soon-card.wobble { animation: shake 0.3s; }

/* ─── Generating / halftone-develop states ─── */
.gen-pending {
  position: relative; overflow: hidden;
  background: repeating-linear-gradient(-45deg, var(--paper-sunk), var(--paper-sunk) 8px, var(--halftone) 8px, var(--halftone) 16px);
  background-size: 200% 200%;
  animation: hatch-drift 1.2s linear infinite;
  border: var(--border-ink); border-radius: var(--radius);
  min-height: 160px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
}
.gen-pending .gp-label { font-family: var(--f-head); font-weight: 700; font-size: 13px; color: var(--ink-soft); }
.gen-pending .gp-pct { font-family: var(--f-mono); font-weight: 700; font-size: 20px; }

.develop-in { animation: develop 0.9s ease-out both; }

/* progress film strip */
.filmstrip-progress {
  height: 14px; border: 2px solid var(--ink-line); border-radius: 7px;
  background-image: radial-gradient(var(--paper-2) 2.4px, transparent 2.6px);
  background-size: 12px 12px; background-color: var(--paper-sunk);
  overflow: hidden; position: relative;
}
.filmstrip-progress .fp-fill {
  position: absolute; inset: 0; width: 0%;
  background-image: radial-gradient(var(--paper-sunk) 2.4px, transparent 2.6px);
  background-size: 12px 12px; background-color: var(--ink);
  transition: width 0.4s ease;
}

/* ─── Page transitions & misc ─── */
.page-enter { animation: page-in 0.3s ease-out both; }
.stack { display: flex; flex-direction: column; gap: 14px; }
.row { display: flex; align-items: center; gap: 10px; }
.grow { flex: 1; min-width: 0; }
.center { text-align: center; }
.muted { color: var(--newsprint-mute); }
.small { font-size: 13px; }

.screen-title {
  font-family: var(--f-display); font-size: 34px; margin: 6px 0 2px;
  display: flex; align-items: center; gap: 10px;
}
.back-tab {
  display: inline-flex; align-items: center; gap: 4px;
  font-family: var(--f-head); font-weight: 600; font-size: 12px;
  color: var(--ink-soft); text-decoration: none;
  background: var(--paper-sunk); border: 2px solid var(--ink-line);
  border-bottom: none; border-radius: 10px 10px 0 0; padding: 4px 14px 6px;
}

/* cost mini-coin badge */
.cost-badge {
  display: inline-flex; align-items: center; gap: 4px;
  font-family: var(--f-mono); font-size: 12px; font-weight: 700;
  background: var(--credit-gold); border: 2px solid var(--ink-line);
  border-radius: 999px; padding: 1px 9px;
  color: var(--ink);
}

/* ─── Keyframes ─── */
@keyframes pow {
  0% { transform: scale(0) rotate(-12deg); opacity: 0; }
  60% { transform: scale(1.15) rotate(3deg); opacity: 1; }
  100% { transform: scale(1) rotate(-4deg); opacity: 1; }
}
@keyframes pow-out { to { transform: scale(0.6) rotate(6deg); opacity: 0; } }
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-3px) rotate(-1deg); }
  75% { transform: translateX(3px) rotate(1deg); }
}
@keyframes inky-bob {
  0%, 100% { transform: translateY(0) scaleY(1); }
  50% { transform: translateY(-4px) scaleY(1.03) scaleX(0.98); }
}
@keyframes inky-pop {
  0% { transform: scale(1); }
  50% { transform: scale(1.25) rotate(-4deg); }
  100% { transform: scale(1); }
}
@keyframes hatch-drift { to { background-position: 32px 32px; } }
@keyframes develop {
  0% { opacity: 0; filter: contrast(3) brightness(1.4) saturate(0); transform: scale(1.02); }
  60% { opacity: 1; filter: contrast(1.4) brightness(1.1) saturate(0.6); }
  100% { opacity: 1; filter: none; transform: scale(1); }
}
@keyframes pop-up {
  0% { transform: translateY(30px) scale(0.9); opacity: 0; }
  100% { transform: translateY(0) scale(1); opacity: 1; }
}
@keyframes page-in {
  0% { transform: translateY(10px); opacity: 0; }
  /* end at `none` so the retained fill never makes an ancestor a containing
     block for position:fixed descendants (e.g. the story player stage) */
  100% { transform: none; opacity: 1; }
}
@keyframes typewriter-caret { 50% { border-color: transparent; } }
@keyframes coin-drop {
  0% { transform: translateY(0) rotateY(0); opacity: 1; }
  100% { transform: translateY(34px) rotateY(540deg); opacity: 0; }
}
@keyframes dice-roll { to { transform: rotate(720deg); } }
.dice-rolling { display: inline-block; animation: dice-roll 0.5s ease-out; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
  .panel--tilt-l, .panel--tilt-r { transform: none; }
}

/* ═══════════════════════════════════════════════════════════════
   DESKTOP ≥ 1024px — the editorial comic "spread"
   ═══════════════════════════════════════════════════════════════ */
@media (min-width: 1024px) {
  body { font-size: 17px; background-color: var(--paper-sunk); }

  .tabbar, .fab { display: none; }

  /* spine rail */
  .spine {
    display: flex; flex-direction: column; align-items: center;
    width: 88px; flex: 0 0 88px;
    position: sticky; top: 0; height: 100vh;
    background: var(--paper-2);
    border-right: 3px solid var(--ink-line);
    padding: 18px 0; gap: 6px; z-index: 45;
  }
  .spine::after { /* perforated spine edge */
    content: ''; position: absolute; right: 4px; top: 0; bottom: 0; width: 4px;
    background-image: radial-gradient(var(--ink-line) 1.4px, transparent 1.6px);
    background-size: 4px 12px; opacity: 0.5;
  }
  .spine .spine-mark {
    font-family: var(--f-display); font-size: 22px; color: var(--ink);
    writing-mode: vertical-rl; transform: rotate(180deg);
    margin-bottom: 16px; text-decoration: none;
  }
  .spine .spine-tab {
    width: 56px; height: 56px; border-radius: 14px;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
    color: var(--newsprint-mute); background: transparent; border: 2px solid transparent;
    font-family: var(--f-head); font-weight: 600; font-size: 9px;
    text-decoration: none; transition: all 0.12s;
  }
  .spine .spine-tab svg { width: 22px; height: 22px; }
  .spine .spine-tab:hover { border-color: var(--ink-line); background: var(--paper-sunk); color: var(--ink); }
  .spine .spine-tab.is-active {
    background: var(--ink); color: var(--paper);
    box-shadow: 2px 2px 0 var(--riso-yellow);
  }
  .spine .spine-bottom { margin-top: auto; display: flex; flex-direction: column; align-items: center; gap: 10px; }

  /* the two-page spread stage */
  .view {
    max-width: 1240px;
    padding: 26px 34px 60px;
  }
  .spread {
    display: grid; grid-template-columns: 1fr 1fr; gap: 0;
    background: var(--paper-2);
    border: var(--border-ink); border-radius: var(--radius-lg);
    box-shadow: 6px 6px 0 var(--panel-shadow);
    /* clip (not hidden): keeps the rounded corners without creating a scroll
       container, so sticky generate bars inside the spread still pin */
    overflow: clip;
  }
  .spread > .page { padding: 28px; min-width: 0; }
  .spread > .page--left { border-right: 1px solid rgba(26,23,18,0.15); }
  .spread > .page--right {
    background: linear-gradient(to right, rgba(26,23,18,0.06), transparent 24px);
  }
  .spread--single { display: block; }

  .masthead { padding: 0 34px; }
  .create-sheet { padding-bottom: 0; justify-content: center; }
}

/* ═══════════════════════════════════════════════════════════════
   Render stage — the page being drawn, panel by panel
   ═══════════════════════════════════════════════════════════════ */
.render-stage {
  display: flex; flex-direction: column; gap: 12px;
  background: var(--paper-2);
  border: var(--border-ink); border-radius: var(--radius);
  box-shadow: var(--shadow-hard);
  padding: 14px;
}
.rs-head { display: flex; align-items: baseline; justify-content: space-between; }
.rs-tag {
  font-size: 10px; font-weight: 700; letter-spacing: 0.14em;
  color: var(--newsprint-mute);
  border: 2px solid var(--ink-line); border-radius: 5px; padding: 1px 7px;
  transform: rotate(-2deg);
}
.rs-pct { font-size: 26px; font-weight: 700; line-height: 1; }

.rs-sheet {
  position: relative; overflow: hidden;
  width: 100%; max-width: 340px; margin: 0 auto;
  aspect-ratio: var(--page-aspect, 2 / 3);
  background: #fff;
  border: 2px solid var(--ink-line); border-radius: 8px;
  box-shadow: 2px 2px 0 var(--panel-shadow);
  padding: 6px;
}
.rs-grid {
  display: grid; gap: 4px; height: 100%;
  grid-template-columns: repeat(6, 1fr); grid-template-rows: repeat(6, 1fr);
}
.rs-panel {
  position: relative; overflow: hidden;
  border: 2px dashed var(--locked-hatch); border-radius: 3px;
  background: var(--paper);
  transition: border-color 0.25s;
}
/* the ink washing in */
.rs-panel .rs-ink {
  position: absolute; inset: 0;
  background:
    repeating-linear-gradient(-45deg, var(--ink-soft) 0 2px, transparent 2px 7px),
    var(--paper-sunk);
  transform: translateY(101%);
  transition: transform 0.5s cubic-bezier(0.3, 1, 0.4, 1);
}
.rs-panel.is-inked { border-style: solid; border-color: var(--ink-line); }
.rs-panel.is-inked .rs-ink { transform: none; }

/* halftone light sweeping the sheet while it works */
.rs-scan {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(105deg, transparent 40%, rgba(255, 255, 255, 0.75) 50%, transparent 60%);
  background-size: 260% 100%;
  animation: rs-sweep 2.1s linear infinite;
}
.rs-nib {
  position: absolute; z-index: 2;
  transform: translate(-50%, -50%) rotate(-18deg);
  font-size: 22px;
  filter: drop-shadow(1px 2px 0 rgba(26, 23, 18, 0.35));
  transition: left 0.5s cubic-bezier(0.3, 1, 0.4, 1), top 0.5s cubic-bezier(0.3, 1, 0.4, 1);
  animation: rs-bob 1.1s ease-in-out infinite;
}
.render-stage.is-finishing .rs-nib { opacity: 0; transition: opacity 0.4s; }
.render-stage.is-queued { opacity: 0.72; }
.render-stage.is-queued .rs-scan,
.render-stage.is-queued .rs-nib { animation-play-state: paused; }
.rs-status { align-items: center; }
.rs-label { font-weight: 600; }

@keyframes rs-sweep { to { background-position: -260% 0; } }
@keyframes rs-bob {
  0%, 100% { margin-top: 0; }
  50% { margin-top: -4px; }
}
@media (prefers-reduced-motion: reduce) {
  .rs-scan, .rs-nib { animation: none; }
}

/* ═══════════════════════════════════════════════════════════════
   Step flow (mobile studios) — one control at a time.
   Mode is chosen by media query alone, so a rotate/resize can't desync it.
   ═══════════════════════════════════════════════════════════════ */
.wiz { display: flex; flex-direction: column; gap: 14px; }
.wiz-steps { display: flex; flex-direction: column; gap: 16px; }

/* numbered comic stamps */
.wiz-rail { display: flex; align-items: center; gap: 6px; padding: 2px 0; }
.wiz-dot {
  flex: 1 1 0; min-width: 0; height: 30px;
  background: var(--paper-sunk); color: var(--newsprint-mute);
  border: 2px solid var(--ink-line); border-radius: 9px;
  font-family: var(--f-display); font-size: 15px; line-height: 1;
  box-shadow: 2px 2px 0 var(--panel-shadow);
  transition: background 0.14s, color 0.14s, transform 0.14s;
}
.wiz-dot.is-done { background: var(--riso-teal); color: #fff; }
.wiz-dot.is-current {
  background: var(--ink); color: var(--paper);
  transform: translateY(-2px) rotate(-2deg);
  box-shadow: 2px 3px 0 var(--riso-yellow);
}

.wiz-head { display: flex; flex-direction: column; gap: 2px; }
.wiz-count { font-size: 10px; letter-spacing: 0.16em; color: var(--newsprint-mute); }
.wiz-title { font-size: 30px; line-height: 1; }
.wiz-hint { margin-top: 2px; }

.wiz-step.wiz-shake { animation: shake 0.35s; }

/* nav doubles as the sticky generate bar */
.wiz-nav {
  position: sticky;
  bottom: calc(var(--tabbar-h) + var(--safe-b) + 20px);
  z-index: 30;
  display: flex; align-items: center; gap: 10px;
  background: var(--paper-2);
  border: var(--border-ink); border-radius: var(--radius);
  box-shadow: var(--shadow-harder);
  padding: 10px 12px;
}
.wiz-nav .is-hidden { display: none; }
.wiz-nav .bubble-btn::after { display: none; }
.wiz-back { flex: 0 0 auto; }
.wiz-next { flex: 1; }
.wiz-finish { flex: 1; display: none; min-width: 0; }
.wiz.is-last .wiz-finish { display: flex; }
.wiz-finish > * { width: 100%; }

@media (max-width: 1023.98px) {
  .wiz-step { display: none; }
  .wiz-step.is-current { display: block; animation: wiz-in 0.26s ease-out both; }
  /* On a phone the nav holds BACK + a cost badge + the action, and the long
     "1 page · 4 panels · queue up to 3" note pushed the button off-screen. The
     review step already lists all of that. */
  .wiz-nav .gb-note { display: none; }
  .wiz-nav .gb-info { flex: 0 0 auto; }
}
@keyframes wiz-in {
  from { opacity: 0; transform: translateX(14px); }
  to { opacity: 1; transform: none; }
}

/* Desktop keeps the spread: every step visible, no rail, no back/next. */
@media (min-width: 1024px) {
  .wiz-rail, .wiz-head, .wiz-back, .wiz-next { display: none; }
  .wiz-step--mobile { display: none; }
  .wiz-finish { display: flex; }
  .wiz-nav { bottom: 18px; }
}

/* ─── Output engine picker (manga + product) ─── */
.engine-picks { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.engine-pick {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  background: var(--speech-fill); color: var(--ink);
  border: 2px solid var(--ink-line); border-radius: 12px;
  padding: 9px 11px; text-align: left;
  box-shadow: 2px 2px 0 var(--panel-shadow);
  transition: transform 0.08s, box-shadow 0.08s, background 0.12s;
}
.engine-pick:active { transform: translate(2px, 2px); box-shadow: 0 0 0 var(--panel-shadow); }
.engine-pick .ep-title { font-size: 17px; line-height: 1.05; }
.engine-pick .ep-tag { font-family: var(--f-mono); font-size: 10px; color: var(--newsprint-mute); }
.engine-pick.is-on { background: var(--ink); color: var(--paper); box-shadow: 2px 2px 0 var(--riso-yellow); }
.engine-pick.is-on .ep-tag { color: var(--riso-yellow); }
.engine-note { margin-top: 7px; min-height: 1.2em; }

/* 4-up product results */
.pr-variants { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.pr-variants .pr-shot { margin: 0; }

/* ─── Fullscreen image viewer ─── */
.is-zoomable { cursor: zoom-in; }
.lb-scrim {
  position: fixed; inset: 0; z-index: 120;
  background: var(--overlay-scrim);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; padding: 14px;
  animation: page-in 0.18s ease-out both;
}
.lb-stage {
  flex: 1; min-height: 0; width: 100%;
  display: flex; align-items: center; justify-content: center;
}
.lb-img {
  max-width: 100%; max-height: 100%;
  width: auto; height: auto; object-fit: contain;
  border: var(--border-ink); border-radius: 8px;
  background: var(--paper-2);
  box-shadow: 6px 6px 0 rgba(0,0,0,0.45);
}
.lb-close {
  position: absolute; top: 12px; right: 12px; z-index: 2;
  width: 40px; height: 40px; border-radius: 12px;
  background: var(--paper-2); color: var(--ink);
  border: var(--border-ink); box-shadow: var(--shadow-harder);
  font-size: 17px; font-weight: 700; line-height: 1;
}
.lb-bar {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
  gap: 12px; flex-wrap: wrap; max-width: 900px;
}
.lb-cap { max-width: 620px; }
@media (max-width: 640px) { .lb-cap { display: none; } }

/* ─── Utility offline banner ─── */
.down-banner {
  display: flex; align-items: center; gap: 10px;
  background: repeating-linear-gradient(45deg, var(--paper-sunk), var(--paper-sunk) 7px, var(--locked-hatch) 7px, var(--locked-hatch) 12px);
  border: 2.5px solid var(--danger-ink); border-radius: var(--radius);
  padding: 10px 12px; margin-bottom: 12px;
  color: var(--ink-soft);
}
.down-banner .db-tag {
  flex: 0 0 auto; font-size: 15px; letter-spacing: 0.06em;
  background: var(--danger); color: #fff;
  border: 2px solid var(--ink-line); border-radius: 8px;
  padding: 2px 9px;
}
.down-banner.is-admin { border-color: var(--riso-blue); }
.down-banner.is-admin .db-tag { background: var(--riso-blue); }

/* locked tool cards in the hubs */
.hub-tool.is-down { filter: saturate(0.35); opacity: 0.72; }
.hub-tool .tc-down {
  display: inline-flex; align-items: center; gap: 4px; margin-top: 4px;
  font-family: var(--f-mono); font-size: 10px; font-weight: 700;
  background: var(--danger); color: #fff;
  border: 2px solid var(--ink-line); border-radius: 999px; padding: 1px 8px;
}
.hub-tool .tc-down.is-admin { background: var(--riso-blue); }
.chip.is-off { opacity: 0.45; }

/* queued page card + per-card progress */
.card-prog { width: 100%; margin-top: 10px; height: 10px; }
.gen-pending.is-queued { opacity: 0.72; }
.engine-picks { grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); }
