/* DEVIATE.ID8 — Consume-campaign visual language: deep teal/navy ground,
   orange as the working accent, cream as the reading color, red reserved
   for the DEVIATION state and the system-selected label, so it keeps
   meaning instead of becoming decoration. Campaign voice (Anton display
   type, uppercase) vs. interface voice (monospace) stays contrasted
   throughout. Background art direction is untouched this pass — the
   product finishing pass (mobile product finishing pass) moved control
   chrome to a modern phone-native pill system: rounded, translucent,
   consistent across every button in the app. */

/* A-tier perf audit: this previously requested Inter 600, which nothing in
   this file actually sets (font-weight:700 is used throughout instead, so
   the browser was silently substituting a nearby weight for every "700"
   and the 600 file was fetched for nothing) — swapped to request the
   weight that's actually used. */
@import url("https://fonts.googleapis.com/css2?family=Anton&family=Inter:wght@400;700;800&display=swap");

:root {
  --bg: #081a1c;
  --bg-2: #0d2a2e;
  --navy: #0b1f36;
  --teal: #1a8a95;
  --teal-dim: #123f45;
  --panel: #0e2226;
  --panel-translucent: rgba(14, 34, 38, 0.72);
  --cream: #f3ead6;
  --cream-dim: rgba(243, 234, 214, 0.64);
  --orange: #ff6a1f;
  --orange-dim: #7a3517;
  --red: #e2131a;
  --red-dim: #4a0f0f;
  --line: rgba(243, 234, 214, 0.18);
  --line-strong: rgba(243, 234, 214, 0.34);
  --mono: "SF Mono", "Courier New", Courier, monospace;
  --sans: "Inter", -apple-system, "Helvetica Neue", Helvetica, Arial, sans-serif;
  --display: "Anton", "Arial Narrow", sans-serif;
}

* { box-sizing: border-box; }

/* ---- B-tier background pass: the campaign poster (DEVIATION/DEVIATE
   BG.jpg, 720x1280, ~289KB) is now the page's own background, full-bleed
   and fixed. app-frame insets over it so the app reads as a polished
   object sitting on top of campaign artwork -- the poster is only ever
   visible in the margin around the frame, never as a wallpaper showing
   through the interface itself. ---- */
body {
  background: var(--bg) url("assets/deviate-campaign-bg.jpg") center top / cover fixed no-repeat;
  color: var(--cream);
  font-family: var(--sans);
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  /* Phase 4: the frame now shrink-wraps to its content (see .app-frame
     below) instead of always stretching to fill the viewport, so this
     centers it vertically when content is shorter than the screen and lets
     more of the campaign background show around it, front and back. */
  justify-content: center;
  padding: 14px;
}

.app-frame {
  position: relative;
  /* Phase 4: was flex:1 (always stretched to fill remaining body height,
     regardless of how little content a given screen actually had — the
     source of PG1's large dead dark region below the old UPLOAD button).
     0 1 auto sizes the frame to its actual content on every screen; body's
     justify-content:center (above) handles vertical centering instead. */
  flex: 0 1 auto;
  display: flex;
  flex-direction: column;
  background: linear-gradient(165deg, var(--navy) 0%, var(--bg) 55%, var(--bg-2) 100%);
  border-radius: 22px;
  overflow: hidden;
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.45);
}
.app-frame::before {
  /* faint structural grid — institutional/controlled-grid texture, clipped
     to the frame's own rounded corners rather than the full viewport */
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(var(--line) 1px, transparent 1px) 0 0 / 100% 32px,
    linear-gradient(90deg, var(--line) 1px, transparent 1px) 0 0 / 32px 100%;
  opacity: 0.12;
  z-index: 0;
}

/* ---- Consistent brand header — one treatment shared by every state
   (opening / rendering / editor). Single line, upper-left: NURA STUDIOS in
   cream, a restrained separator, DEVIATE in orange. No URL subtext, no
   second branding row. ID8 wayfinding sits opposite, small, so it never
   competes with product branding. ---- */
.app-brand {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 16px;
}
.app-brand-lockup {
  display: flex;
  align-items: center;
  gap: 7px;
  text-decoration: none;
  color: var(--cream);
}
.app-brand-logo {
  width: 18px;
  height: 18px;
  object-fit: contain;
}
.app-brand-nura-name {
  font-family: var(--display);
  font-weight: 400;
  font-size: 14px;
  letter-spacing: 0.05em;
  color: var(--cream);
}
.app-brand-lockup:hover .app-brand-nura-name { color: var(--orange); }
.app-brand-sep {
  color: var(--line-strong);
  font-family: var(--display);
  font-size: 14px;
}
.app-brand-deviate {
  text-decoration: none;
  font-family: var(--display);
  font-weight: 400;
  font-size: 15px;
  letter-spacing: 0.06em;
  color: var(--orange);
}
.app-brand-deviate:hover { color: #ff7f3f; }
.app-brand-id8 {
  margin-left: auto;
  color: var(--cream-dim);
  text-decoration: none;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  font-weight: 700;
}
.app-brand-id8:hover { color: var(--orange); }

.app-shell {
  position: relative;
  z-index: 1;
  display: flex;
  justify-content: center;
  padding: 6px 20px 20px;
}

.view {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 480px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* Several elements below set an explicit `display` to toggle visibility via
   the `hidden` attribute from JS. Equal-specificity class selector vs. the
   UA [hidden]{display:none} rule means source order decides — ours would
   otherwise win and defeat `hidden`. One reset restores it everywhere. */
[hidden] {
  display: none !important;
}

/* ---- Phase 4: one progressive primary action, now built around the
   approved square campaign artwork instead of a text title + outlined
   button. The artwork itself carries the "DEVIATE MEME MAKER" wordmark and
   IS the upload CTA (PG1); app.js swaps this same <img> to the uploaded
   photo in place once one's chosen (PG2), so the dominant image area never
   resizes — only its content changes. Governing rule: campaign image ->
   uploaded image -> generated image (view-editor's composer-canvas-wrap)
   all occupy essentially the same footprint. ---- */
.primary-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.stage-visual {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: 16px;
  overflow: hidden;
  background: var(--panel);
  border: 1px solid var(--line-strong);
}
.stage-visual-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.stage-visual.is-dragover {
  border-color: var(--orange);
  box-shadow: inset 0 0 0 2px var(--orange);
}
/* B-tier stability pass: was a small bottom-anchored mono pill — real
   feedback called it too small and too low to read as the main CTA. Now a
   large, display-type badge centered over the artwork (roughly the woman's
   chest), ~2.5x the prior visual weight, so it's unmistakably the primary
   action rather than a caption. Only shown pre-upload (PG1); app.js hides
   it permanently the moment a photo lands. */
.stage-visual-hint {
  position: absolute;
  left: 50%;
  top: 58%;
  transform: translate(-50%, -50%);
  background: rgba(8, 26, 28, 0.8);
  border: 2px solid var(--orange);
  border-radius: 999px;
  padding: 16px 32px;
  font-family: var(--display);
  font-weight: 400;
  font-size: 26px;
  letter-spacing: 0.05em;
  color: var(--cream);
  text-align: center;
  white-space: nowrap;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.4);
}
/* Frontend polish pass: the hint badge above is now the single primary
   entry action itself (a real <button>, id btn-deviate-entry) rather than
   a non-interactive label sitting on top of a clickable wrapper — needs
   its own pointer-events/cursor/font-reset since .stage-visual-hint no
   longer inherits click-ability from a <label> parent. */
.stage-visual-cta {
  pointer-events: auto;
  cursor: pointer;
  font: inherit;
  appearance: none;
}
.stage-visual-cta:hover { border-color: #ff7f3f; }
/* TAKE A PHOTO / UPLOAD A PHOTO — revealed in the same spot once DEVIATE
   is tapped, reusing the existing .pill-btn-primary look so no new button
   styling is needed, just a stacked layout for the two choices. */
.entry-chooser {
  position: absolute;
  left: 50%;
  top: 58%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: min(80%, 320px);
}
.entry-chooser .pill-btn { width: 100%; }

.camera-panel {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: 16px;
  overflow: hidden;
  background: var(--panel);
  border: 1px solid var(--line-strong);
}
.camera-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  background: #000;
}
/* Automatic-countdown pass: a brief translucent red pulse behind the
   countdown number each step -- a warning/scanner feel, not an opaque
   screen, so the person stays clearly visible through it. Always in the
   DOM at opacity:0 (not [hidden]-toggled) so the opacity transition can
   actually animate every time app.js adds/removes .is-flashing. */
.camera-flash {
  position: absolute;
  inset: 0;
  background: rgba(220, 38, 38, 0.35);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
}
.camera-flash.is-flashing {
  opacity: 1;
}
/* Countdown overlay (3/2/1), centered over the preview. pointer-events:none
   so CANCEL underneath stays clickable while it's showing. */
.camera-countdown {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  font-family: var(--display);
  font-weight: 400;
  font-size: 64px;
  letter-spacing: 0.08em;
  color: var(--cream);
  text-shadow: 0 0 12px rgba(0, 0, 0, 0.9), 0 0 32px rgba(0, 0, 0, 0.7);
  background: rgba(8, 26, 28, 0.25);
}
.camera-panel-controls {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  gap: 8px;
  padding: 12px;
  background: linear-gradient(to top, rgba(8, 26, 28, 0.85), transparent);
}
.camera-panel-controls .pill-btn { flex: 1; }

/* ---- PG2 compact control row: "DIRECT THE DEVIATION [input] | DEVIATE".
   Stacked on narrow phones, one line once there's room (desktop breakpoint
   below flips this to row layout). ---- */
.stage-controls {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.direct-panel {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--panel-translucent);
  border: 1px solid var(--line-strong);
  border-radius: 14px;
  padding: 6px 12px;
}
.direct-input {
  flex: 1;
  min-width: 0;
  background: transparent;
  border: none;
  color: var(--cream);
  font-family: var(--sans);
  font-size: 15px;
  padding: 8px 0;
}
.direct-input:focus { outline: none; }
.direct-input::placeholder { color: var(--cream-dim); }
.direct-count {
  flex-shrink: 0;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--cream-dim);
}

.deviate-btn {
  min-height: 60px;
  background: var(--orange);
  color: #0a0a0a;
  border: none;
  border-radius: 18px;
  font-family: var(--display);
  font-weight: 400;
  font-size: 24px;
  letter-spacing: 0.08em;
  cursor: pointer;
}
.deviate-btn:hover { background: #ff7f3f; }

/* ---- SYSTEM LOCKDOWN fallback mode (cost-governance §5) — a curated
   static campaign image + the user's own slogan, composed through the
   exact same editor as a normal generation. Deliberately reuses the red
   "system determination" voice already established for the DEVIATION
   label stamp elsewhere in the app, so it reads as intentional campaign
   messaging, not a broken/degraded error state. ---- */
.lockdown-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: stretch;
}
.lockdown-heading {
  font-family: var(--display);
  font-weight: 400;
  font-size: 26px;
  letter-spacing: 0.04em;
  color: var(--red);
  text-align: center;
  margin: 0;
}
.lockdown-line {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--cream-dim);
  text-align: center;
  margin: 0;
}
.lockdown-picker {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 6px 0;
}
.lockdown-picker-thumb {
  flex: 1;
  aspect-ratio: 4 / 5;
  border-radius: 14px;
  background-color: var(--panel);
  background-size: cover;
  background-position: center;
  border: 1px solid var(--line-strong);
}
.lockdown-picker-arrow {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: var(--panel-translucent);
  color: var(--cream);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}
.lockdown-picker-arrow:hover { border-color: var(--orange); }

.input-status {
  font-family: var(--mono);
  font-size: 13px;
  color: var(--red);
  text-align: center;
  margin: 0;
}

/* SHARE/DOWNLOAD feedback (app.js) -- same convention as .input-status
   (hidden by default, toggled via the hidden attribute), a neutral/success
   color by default since most messages here are confirmations, not errors;
   .is-error switches to the same red .input-status uses for failures. */
.editor-status {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--teal);
  text-align: center;
  margin: 0;
}
.editor-status.is-error {
  color: var(--red);
}

/* Low-priority post-creation CTA -- deliberately quiet (small, dim, no pill
   background) so it never competes with START OVER / SHARE for attention. */
.editor-oatz-cta {
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.5;
  color: var(--cream-dim);
  text-align: center;
  margin: 4px 0 0;
}
.editor-oatz-cta a {
  color: var(--cream-dim);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.editor-oatz-cta a:hover {
  color: var(--orange);
}

/* ---- Unified editor: the image itself is the editor — deterministic
   composition, no AI re-render, redrawn on every edit, rendered as-is. No
   permanent selection-rectangle border — it should sit naturally in the
   UI, not look like a wireframe. ---- */
.view-editor {
  gap: 12px;
}
.composer-canvas-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 5;
  border-radius: 16px;
  overflow: hidden;
  cursor: grab;
  touch-action: none;
  background: var(--panel);
}
.composer-canvas-wrap:active {
  cursor: grabbing;
}
#composer-canvas {
  width: 100%;
  height: 100%;
  display: block;
}

/* Rendering state = the Nura buzz reel, full-bleed within the frame, no
   debug spinner, no editor instructions overlaid on top of it. Phase 6:
   three zones — TOP (status + rotating Nura mark), CENTER (the buzz reel,
   unchanged), BOTTOM (a much larger cycling campaign line). Reads as a
   campaign interstitial, not a technical waiting screen. */
.editor-loading {
  position: absolute;
  inset: 0;
}
.buzz-reel {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.loading-top {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 16px 18px 26px;
  background: linear-gradient(to bottom, rgba(8, 26, 28, 0.85), transparent);
}
.loading-spinner {
  width: 18px;
  height: 18px;
  object-fit: contain;
  animation: nura-spin 1.6s linear infinite;
}
@keyframes nura-spin {
  to { transform: rotate(360deg); }
}
.loading-status {
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--cream);
  margin: 0;
}
.loading-bottom {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 22px 20px 26px;
  background: linear-gradient(to top, rgba(8, 26, 28, 0.92), transparent);
  text-align: center;
}
.loading-slogan {
  font-family: var(--display);
  font-weight: 400;
  font-size: 30px;
  line-height: 1.06;
  letter-spacing: 0.02em;
  color: var(--orange);
  margin: 0;
  min-height: 2.2em;
  text-shadow: 2px 2px 0 rgba(8, 26, 28, 0.55);
}

/* Composer image failed to load/decode -- see app.js's loadComposerImage.
   Same full-frame overlay treatment as .editor-loading (inherited via the
   shared class), centered content instead of the three-zone buzz-reel
   layout. */
.editor-error {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 24px;
  text-align: center;
  background: var(--panel);
}
.editor-error .loading-status {
  color: var(--cream);
}
/* .pill-btn's flex:1 (styles.css above, meant for equal-width buttons in
   a horizontal row like .editor-bottom-row) would otherwise stretch
   RETRY to fill this container's full vertical space, since .editor-error
   is a column flex context -- found live via screenshot verification. */
.editor-error .pill-btn {
  flex: none;
  padding-left: 28px;
  padding-right: 28px;
}

.editor-controls {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* ---- Shared pill button system: rounded, translucent/dark surfaces,
   subtle borders, clear selected states. Applied consistently to the
   four-state selector, the six system labels, TEXT/ROTATE, RENDER/SHARE/
   COPY/DOWNLOAD, and START OVER. ---- */
.pill {
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: var(--panel-translucent);
  color: var(--cream);
  font-family: var(--mono);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.05em;
  cursor: pointer;
  min-height: 40px;
  padding: 8px 10px;
}
.pill:hover { border-color: var(--orange); }

/* ---- Discrete snapped slider — same four underlying states
   (DEFAULT/SHIFT/BREAK/DEVIATION). One pill rail with a sliding capsule
   thumb positioned by JS (measured against each button's own layout, so it
   never drifts from real button edges), not four independent buttons.
   State changes are still instant — only the thumb's position animates. ---- */
.level-slider {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  background: var(--panel-translucent);
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  padding: 4px;
}
.level-slider-thumb {
  position: absolute;
  top: 4px;
  bottom: 4px;
  left: 4px;
  width: 25%;
  background: var(--orange);
  border-radius: 999px;
  transition: left 0.22s cubic-bezier(0.4, 0, 0.2, 1), width 0.22s cubic-bezier(0.4, 0, 0.2, 1), background 0.15s ease;
  z-index: 0;
}
.level-slider-thumb.is-deviation { background: var(--red); }
.level-slider-btn {
  position: relative;
  z-index: 1;
  background: none;
  border: none;
  padding: 8px 4px;
  min-height: 36px;
  font-family: var(--mono);
  font-weight: 700;
  font-size: 10.5px;
  letter-spacing: 0.04em;
  color: var(--cream-dim);
  cursor: pointer;
  text-align: center;
  transition: color 0.15s ease;
}
.level-slider-btn.is-selected { color: #0a0a0a; }
.level-slider-btn.is-selected.is-deviation { color: var(--cream); }

/* Multiple-choice classification restore: 3-4 locked-bank labels, one
   flagged as the active selection (red outline/wash, matching the
   DEVIATION "system determination" red used elsewhere), the rest plain
   .pill buttons. */
.editor-deviation-heading {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--cream-dim);
  margin: 0 0 6px;
}
.composer-classifications {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.label-pill {
  text-align: center;
  font-size: 11px;
}
.label-pill.is-selected {
  background: rgba(226, 19, 26, 0.14);
  border: 2px solid var(--red);
  color: var(--red);
  font-weight: 800;
}

/* Only two headline controls: TEXT (visibility) and ROTATE (0/90/180/270).
   Direct manipulation on the canvas handles position and size. */
.editor-text-controls {
  display: flex;
  gap: 8px;
}
.pill-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 1;
  justify-content: center;
}
.pill-toggle input[type="checkbox"] {
  accent-color: var(--orange);
  width: 15px;
  height: 15px;
}
.pill-btn {
  flex: 1;
  text-align: center;
}

/* Final row: START OVER | SHARE, left to right. START OVER is a secondary
   ghost pill; SHARE is the one solid primary action — composing the final
   JPEG and opening the native share sheet in a single press (no separate
   RENDER step, no COPY/DOWNLOAD). Cost-simplification pass: REMIX removed. */
.editor-bottom-row {
  display: flex;
  gap: 8px;
}
/* Equal pill height across the row regardless of ghost/primary weight, so
   START OVER / SHARE read as one aligned row, not mismatched controls. */
.editor-bottom-row .pill-btn { min-height: 48px; }
.pill-btn-primary {
  background: var(--orange);
  border-color: var(--orange);
  color: #0a0a0a;
  font-family: var(--display);
  font-weight: 400;
  font-size: 18px;
  letter-spacing: 0.05em;
  min-height: 52px;
}
.pill-btn-primary:hover { background: #ff7f3f; }
.pill-btn-ghost {
  background: transparent;
  color: var(--cream-dim);
  font-size: 11px;
  min-height: 36px;
}

/* ---- Phase 5 / B-tier stability pass: restrained but intentional stacked
   footer shared by every screen (PG1/PG2/PG3/loading/lockdown) — not the
   in-canvas Nura provenance mark, which travels with exported memes; this
   is interface chrome only. Was a small horizontal gray line; real
   feedback called it too subdued. Now stacked (slogan on top, domain
   below), sized up, and in the same cream brand family as the header
   instead of a dimmed/gray tone — still compact, not a second large panel. ---- */
.app-footer {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 12px 16px 16px;
  border-top: 1px solid var(--line);
}
.app-footer-slogan {
  font-family: var(--display);
  font-weight: 400;
  font-size: 17px;
  letter-spacing: 0.04em;
  color: var(--cream);
}
.app-footer-domain {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--cream);
  text-decoration: none;
  opacity: 0.85;
}
.app-footer-domain:hover {
  color: var(--orange);
  opacity: 1;
}

/* ---- Desktop: a little more breathing room, same interaction model. The
   frame gets a real max-width and sits centered so it doesn't stretch into
   an unreadable wide bar -- the campaign background still shows around it
   on all sides, same "object over artwork" feel as phone. ---- */
@media (min-width: 700px) {
  body { padding: 28px; align-items: center; }
  .app-frame { max-width: 560px; width: 100%; }
  .app-shell { padding: 10px 24px 20px; }
  /* Phase 4 PG2: "DIRECT THE DEVIATION [input] | DEVIATE" on one line once
     there's room, instead of the mobile stacked layout. */
  .stage-controls { flex-direction: row; align-items: center; }
  .deviate-btn { flex-shrink: 0; width: auto; padding: 0 28px; }
}
