/* ==========================================================================
   Gal Anonim — styles.css
   Implements the GalAnomin Figma design (cream paper + purple ink, Montserrat /
   Inconsolata, glassmorphism, gradient accents, redacted-document motif).
   Styles the live app (index.html); runtime states are toggled by app.js. No build step.
   ========================================================================== */

/* ---------------------------------------------------------------- Tokens -- */
:root {
  /* Brand core */
  --violet:       #1A0635;   /* primary ink / darkest */
  --seance:       #6B1A89;   /* accent purple */
  --mulled-wine:  #4A3B5A;   /* soft ink */
  --doc-ink:      #1A1408;   /* warm near-black — redaction bars */
  --paper:        #F6F3EE;   /* cream background */
  --jagger:       #3D0E60;   /* deep purple surface */
  --red-damask:   #D65A44;   /* coral / danger */
  --coral-2:      #E87963;
  --pastel-green: #6EE7A3;
  --gold:         #F5D33A;

  /* Gradient stops */
  --magenta:      #D24AA0;
  --pink-bright:  #FFB4DC;

  --grad-brand: linear-gradient(135deg, var(--seance) 0%, var(--magenta) 52%, var(--pink-bright) 100%);
  --grad-ink:   linear-gradient(135deg, var(--violet) 0%, var(--jagger) 100%);

  /* Semantic */
  --bg:          var(--paper);
  --ink:         var(--violet);
  --ink-soft:    var(--mulled-wine);
  --accent:      var(--seance);
  --surface:     #FFFFFF;
  --hairline:    rgba(26, 6, 53, 0.14);
  --hairline-2:  rgba(26, 6, 53, 0.30);
  --chip-bg:     rgba(107, 26, 137, 0.06);
  --focus:       var(--coral-2);
  --danger:      var(--red-damask);
  --danger-soft: rgba(214, 90, 68, 0.10);

  /* Glass */
  --glass-blur:   blur(10px);

  /* Type */
  --font-display: "Montserrat", system-ui, -apple-system, sans-serif;
  --font-mono:    "Inconsolata", ui-monospace, "SF Mono", monospace;
  --tracking-eyebrow: 0.18em;
  --tracking-btn:     0.14em;
  --tracking-mono:    0.08em;

  /* Spacing */
  --s-xs: 8px;  --s-sm: 10px;  --s-md: 14px;  --s-lg: 17px;
  --s-xl: 28px; --s-2xl: 44px; --s-3xl: 72px;

  /* Radius & shadow */
  --r-sm: 8px;  --r-md: 14px;  --r-lg: 22px;  --r-pill: 999px;
  --shadow-soft: 0 18px 50px -24px rgba(26, 6, 53, 0.45);
  --shadow-card: 0 2px 1px rgba(255,255,255,0.6) inset, 0 24px 60px -32px rgba(26,6,53,0.55);

  --maxw: 1200px;
}

/* ----------------------------------------------------------------- Reset -- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  font-family: var(--font-display);
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink);
  background-color: var(--bg);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg { display: block; }
button, textarea, input { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; padding: 0; }

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: 3px;
}

.skip-link {
  position: absolute;
  left: 12px; top: -48px;
  background: var(--violet);
  color: var(--paper);
  padding: 10px 16px;
  border-radius: var(--r-sm);
  font: 600 13px/1 var(--font-mono);
  letter-spacing: var(--tracking-mono);
  transition: top .2s ease;
  z-index: 100;
}
.skip-link:focus { top: 12px; }

/* Shared eyebrow / mono-label treatment */
.hero-eyebrow, .panel-eyebrow, .summary-eyebrow, .m-idx,
.brand-tag, .readonly-badge, .char-counter, .shortcut-hint,
.file-drop-formats, .ledger-idx, .ledger-caption,
.footer-sig, .preview-caption {
  font-family: var(--font-mono);
  font-weight: 600;
  letter-spacing: var(--tracking-mono);
}

/* ------------------------------------------------------------- Top nav --- */
.top-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-lg);
  max-width: var(--maxw);
  margin: 0 auto;
  padding: var(--s-lg) var(--s-xl);
}
.brand { display: inline-flex; align-items: center; gap: 12px; }
.brand-mark {
  display: grid; place-items: center;
  width: 38px; height: 38px;
  border-radius: 11px;
  color: var(--paper);
  background: var(--grad-ink);
  box-shadow: var(--shadow-soft);
}
.brand-meta { display: flex; flex-direction: column; line-height: 1.1; }
.brand-name { font-weight: 800; font-size: 16px; letter-spacing: -0.01em; }
.brand-tag {
  font-size: 10px; text-transform: uppercase;
  color: var(--accent); margin-top: 2px;
}
.top-links { display: flex; align-items: center; gap: var(--s-xl); }
.top-links a {
  font-size: 13px; font-weight: 600; color: var(--ink-soft);
  transition: color .15s ease;
}
.top-links a:hover { color: var(--accent); }
.link-strong {
  color: var(--violet) !important;
  padding: 7px 14px;
  border: 1px solid var(--hairline-2);
  border-radius: var(--r-pill);
}
.link-strong:hover {
  background: var(--violet); color: var(--paper) !important;
  border-color: var(--violet);
}
.nav-github { color: var(--ink-soft); transition: color .15s ease; }
.nav-github:hover { color: var(--accent); }

/* --------------------------------------------------------------- Hero ---- */
/* Full-bleed gradient band. Inner content stays capped at --maxw via padding. */
.hero {
  margin: 0;
  padding: var(--s-3xl) max(var(--s-xl), calc((100% - var(--maxw)) / 2));
  background-color: var(--jagger);
  background-image:
    radial-gradient(75% 120% at 100% 0%, rgba(255, 180, 220, 0.55), transparent 55%),
    radial-gradient(60% 90% at 0% 100%, rgba(107, 26, 137, 0.55), transparent 60%),
    var(--grad-brand);
  color: #fff;
}
.hero-grid {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: var(--s-3xl);
  align-items: center;
}
.hero-eyebrow {
  display: inline-block;
  font-size: 12px; text-transform: uppercase;
  letter-spacing: var(--tracking-eyebrow);
  color: rgba(255, 255, 255, 0.72);
  margin-bottom: var(--s-md);
}
#hero-title {
  font-weight: 800;
  font-size: clamp(34px, 5vw, 56px);
  line-height: 1.04;
  letter-spacing: -0.025em;
  color: #fff;
}
/* Accent word: solid light pink on the gradient (not gradient-clipped) */
.marker {
  position: relative;
  white-space: nowrap;
  color: var(--pink-bright);
}
.hero-sub {
  margin-top: var(--s-lg);
  max-width: 46ch;
  font-size: 16px;
  color: rgba(255, 255, 255, 0.85);
}
.hero-sub code {
  font-family: var(--font-mono);
  font-size: 0.85em;
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
  padding: 1px 6px;
  border-radius: 5px;
}
.hero-sub em { font-style: normal; font-weight: 700; color: #fff; }

.manifesto-strip {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--s-md);
  margin-top: var(--s-2xl);
}
.manifesto-strip li {
  display: flex; flex-direction: column; gap: 4px;
  padding: var(--s-md) var(--s-lg);
  background: rgba(255, 255, 255, 0.12);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: var(--r-md);
  box-shadow: 0 18px 40px -28px rgba(0, 0, 0, 0.6);
  /* staggered reveal */
  opacity: 0;
  animation: rise .6s cubic-bezier(.2,.7,.2,1) forwards;
}
.manifesto-strip li:nth-child(1) { animation-delay: .05s; }
.manifesto-strip li:nth-child(2) { animation-delay: .12s; }
.manifesto-strip li:nth-child(3) { animation-delay: .19s; }
.manifesto-strip li:nth-child(4) { animation-delay: .26s; }
.m-idx { font-size: 10px; text-transform: uppercase; color: var(--pink-bright); }
.m-statement { font-weight: 700; font-size: 14px; color: #fff; }
.m-detail { font-size: 12.5px; color: rgba(255, 255, 255, 0.78); line-height: 1.4; }

/* Hero document card (paper + redaction) with gold sticky-note + pink glow */
.hero-card-stack { position: relative; }
/* pink glow */
.hero-card-shadow {
  position: absolute; inset: 8px -24px -16px 8px;
  background: var(--pink-bright);
  filter: blur(48px); opacity: 0.55;
  border-radius: var(--r-lg);
}
/* gold sticky-note peeking out behind the card */
.hero-card-stack::before {
  content: ""; position: absolute;
  inset: 34px -20px -24px 46px;
  background: var(--gold);
  border-radius: 6px;
  transform: rotate(4deg);
  box-shadow: 0 20px 45px -25px rgba(0, 0, 0, 0.55);
}
.hero-card {
  position: relative;
  z-index: 1;
  padding: var(--s-xl);
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-card);
  transform: rotate(-1.4deg);
  transition: transform .3s ease;
}
/* floating "14 zamaskowanych fragmentów" pill */
.hero-card-stack::after {
  content: "14 zamaskowanych fragmentów";
  position: absolute; z-index: 2;
  left: 50%; bottom: -18px; transform: translateX(-30%);
  font: 700 11px/1 var(--font-mono);
  letter-spacing: var(--tracking-mono);
  color: var(--violet);
  background: #fff;
  padding: 10px 16px;
  border-radius: var(--r-pill);
  box-shadow: var(--shadow-soft);
  white-space: nowrap;
}
.hero-card:hover { transform: rotate(0deg); }
.hero-card-head {
  display: flex; justify-content: space-between;
  font: 600 10px/1 var(--font-mono);
  letter-spacing: var(--tracking-mono);
  text-transform: uppercase;
  color: var(--ink-soft);
  padding-bottom: var(--s-md);
  margin-bottom: var(--s-md);
  border-bottom: 1px dashed var(--hairline-2);
}
.doc-line {
  font-family: var(--font-mono);
  font-size: 14px;
  color: var(--violet);
  margin-bottom: 8px;
}
.bar {
  display: inline-block;
  background: var(--doc-ink);
  border-radius: 2px;
  vertical-align: middle;
  height: 0.9em;
}
.stamp {
  position: absolute;
  right: var(--s-lg); bottom: var(--s-lg);
  transform: rotate(-8deg);
  font: 800 13px/1 var(--font-display);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--red-damask);
  border: 2px solid var(--red-damask);
  border-radius: 6px;
  padding: 6px 10px;
  opacity: 0.85;
}

/* ----------------------------------------------------------- Workspace --- */
.workspace {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: var(--s-xl);
}
.panel {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}
.panel-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  flex-wrap: wrap; gap: var(--s-lg);
  padding: var(--s-xl);
  border-bottom: 1px solid var(--hairline);
  background: linear-gradient(180deg, rgba(107,26,137,0.04), transparent);
}
.panel-eyebrow {
  display: block; font-size: 11px; text-transform: uppercase;
  letter-spacing: var(--tracking-eyebrow); color: var(--accent);
  margin-bottom: 6px;
}
.panel-title { font-weight: 800; font-size: 22px; letter-spacing: -0.02em; }
.panel-head-controls { display: flex; align-items: center; gap: var(--s-md); }

.input-mode-tabs {
  display: inline-flex;
  background: var(--chip-bg);
  border: 1px solid var(--hairline);
  border-radius: var(--r-pill);
  padding: 4px;
}
.input-tab {
  display: inline-flex; align-items: center; gap: 7px;
  border: none; background: transparent; cursor: pointer;
  font-size: 11px; font-weight: 700; color: var(--ink-soft);
  text-transform: uppercase; letter-spacing: var(--tracking-btn);
  padding: 9px 16px; border-radius: var(--r-pill);
  transition: all .15s ease;
}
.input-tab.is-active {
  background: linear-gradient(135deg, var(--seance) 0%, var(--magenta) 100%);
  color: #fff;
  box-shadow: var(--shadow-soft);
}
.try-example {
  display: inline-flex; align-items: center; gap: 7px;
  border: 1px dashed var(--hairline-2); background: transparent;
  cursor: pointer; color: var(--accent);
  font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: var(--tracking-btn);
  padding: 9px 15px; border-radius: var(--r-pill);
  transition: all .15s ease;
}
.try-example:hover { background: var(--chip-bg); border-style: solid; }

/* Editors */
.editor-grid {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 1px;
  background: var(--hairline);
}
.editor {
  position: relative;
  display: flex; flex-direction: column;
  background: var(--surface);
  padding: var(--s-lg) var(--s-xl) var(--s-md);
  /* min-width:0 lets the grid track honour its 1fr share instead of growing to
     fit min-content (long filenames, the output controls) and squeezing the
     other column — the same blowout class as the output-width bug. */
  min-width: 0;
}
.editor-label {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 12px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--ink-soft);
  margin-bottom: var(--s-md);
}
.dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px var(--chip-bg);
}
.dot.out { background: var(--pastel-green); box-shadow: 0 0 0 3px rgba(110,231,163,0.18); }

.editor-area {
  flex: 1;
  min-height: 320px;
  resize: vertical;
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  padding: var(--s-md);
  font-family: var(--font-mono);
  font-size: 13.5px; line-height: 1.7;
  color: var(--violet);
  background: #FDFCFA;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.editor-area:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 4px var(--chip-bg);
}
/* Output content swaps between preview / skeleton / textarea / error host.
   Make the host a stretching flex column so every state fills the column to
   the same width as the input textarea (otherwise the injected textarea falls
   back to its intrinsic cols-based width and the panel narrows on Anonimizuj). */
#output-body { display: flex; flex-direction: column; flex: 1; }
.editor-area.is-output {
  width: 100%;
  /* Read-only output — manual resize is pointless and gets reset on the next
     state swap anyway, so disable it. */
  resize: none;
  background: #FDFCFA;
  color: var(--doc-ink);
  border-color: var(--hairline);
}
.editor-actions {
  position: absolute; top: var(--s-lg); right: var(--s-xl);
  display: flex; gap: 6px;
}
.copy-floating {
  display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid var(--hairline-2); background: var(--surface);
  cursor: pointer; color: var(--ink-soft);
  font-size: 11px; font-weight: 700;
  padding: 6px 10px; border-radius: var(--r-pill);
  transition: all .15s ease;
}
.copy-floating:hover { color: var(--accent); border-color: var(--accent); }
.editor-foot {
  display: flex; justify-content: flex-end;
  margin-top: var(--s-sm); min-height: 20px;
}
.char-counter { font-size: 11px; color: var(--ink-soft); }
.char-counter.has-error, .char-num.has-error { color: var(--red-damask); font-weight: 700; }
.readonly-badge {
  font-size: 10px; text-transform: uppercase; color: var(--ink-soft);
  background: var(--chip-bg); padding: 3px 9px; border-radius: var(--r-pill);
}

/* Action bar + buttons */
.action-bar {
  display: flex; align-items: center; gap: var(--s-md); flex-wrap: wrap;
  padding: var(--s-lg) var(--s-xl);
  border-top: 1px solid var(--hairline);
}
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  border: none; cursor: pointer;
  font-family: var(--font-display);
  font-weight: 700; font-size: 12px;
  letter-spacing: var(--tracking-btn); text-transform: uppercase;
  padding: 14px 22px; border-radius: var(--r-pill);
  transition: transform .15s ease, background .15s ease, box-shadow .15s ease;
}
.btn:active { transform: translateY(1px); }
/* Fixed width so the label cycling Anonimizuj / Anonimizuj plik / Przetwarzanie…
   (app.js setMode/setBusy) doesn't resize the button and shift Wyczyść beside it. */
#btn-anonymize { min-width: 210px; }
.btn-primary { background: var(--red-damask); color: #fff; box-shadow: var(--shadow-soft); }
.btn-primary:hover { background: var(--coral-2); transform: translateY(-1px); }
.btn-primary:disabled { opacity: .45; cursor: not-allowed; transform: none; box-shadow: none; }
.btn-secondary { background: var(--chip-bg); color: var(--violet); }
.btn-secondary:hover:not(:disabled) { background: rgba(107,26,137,0.12); }
.btn-secondary:disabled { opacity: .45; cursor: not-allowed; }
.btn-outline { background: transparent; color: var(--violet); border: 1.5px solid var(--hairline-2); }
.btn-outline:hover { border-color: var(--violet); background: var(--surface); }
.shortcut-hint { margin-left: auto; font-size: 11px; color: var(--ink-soft); }
kbd {
  font-family: var(--font-mono); font-size: 10.5px;
  background: var(--chip-bg); border: 1px solid var(--hairline-2);
  border-radius: 5px; padding: 2px 6px;
}

/* --------------------------------------------------- Detection summary --- */
.detection-summary { padding: var(--s-xl); border-top: 1px solid var(--hairline); }
.summary-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--s-lg); flex-wrap: wrap; margin-bottom: var(--s-lg);
}
.summary-eyebrow {
  display: block; font-size: 11px; text-transform: uppercase;
  letter-spacing: var(--tracking-eyebrow); color: var(--accent); margin-bottom: 5px;
}
.summary-title-large { font-weight: 800; font-size: 20px; letter-spacing: -0.02em; }
.summary-help { font-size: 12px; color: var(--ink-soft); max-width: 30ch; text-align: right; }

.ledger { display: flex; flex-direction: column; }
.ledger-row, .ledger-total {
  display: grid;
  grid-template-columns: 30px 1fr auto 120px;
  align-items: center; gap: var(--s-md);
  padding: 11px 0;
  border-bottom: 1px solid var(--hairline);
}
.ledger-row {
  opacity: 0;
  animation: rise .5s ease forwards;
  animation-delay: calc(var(--idx, 0) * 0.05s);
}
.ledger-idx { font-size: 11px; color: var(--ink-soft); }
.ledger-name { font-weight: 600; font-size: 14px; color: var(--violet); }
.ledger-count {
  font-family: var(--font-mono); font-weight: 700; font-size: 14px;
  color: var(--accent); justify-self: end;
}
.ledger-bar {
  display: block; height: 8px; width: 100%;
  background: rgba(26, 6, 53, 0.08); border-radius: var(--r-pill); overflow: hidden;
}
.ledger-bar-fill {
  display: block; height: 100%; width: var(--w, 0%);
  background: linear-gradient(90deg, var(--seance), var(--red-damask));
  border-radius: var(--r-pill);
  transform-origin: left; animation: grow .8s ease forwards;
}
.ledger-total { border-bottom: none; padding-top: var(--s-md); }
.ledger-total .ledger-idx { font-weight: 700; color: var(--violet); }
.ledger-total .ledger-name { font-weight: 800; }
.ledger-total .ledger-count { color: var(--violet); font-size: 16px; }
.ledger-caption { font-size: 11px; color: var(--ink-soft); justify-self: start; }

/* Explainer */
.explainer {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-lg);
  margin-top: var(--s-xl);
}
.explainer-col {
  padding: var(--s-lg);
  background: var(--chip-bg);
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
}
.explainer-col h3 {
  font-size: 13px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--accent); margin-bottom: var(--s-sm);
}
.explainer-col.kept { background: rgba(110,231,163,0.10); }
.explainer-col.kept h3 { color: #2f8f5b; }
.explainer-col li {
  font-size: 13px; color: var(--ink-soft);
  padding-left: 18px; position: relative; margin-bottom: 6px;
}
.explainer-col li::before {
  content: ""; position: absolute; left: 0; top: 8px;
  width: 6px; height: 6px; border-radius: 50%; background: var(--accent);
}
.explainer-col.kept li::before { background: var(--pastel-green); }
.explainer-col strong { color: var(--violet); }

/* ---------------------------------------------------------- Desktop CTA -- */
/* Sits inside the width-capped .workspace, so break out to full-bleed. */
.desktop-cta {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-lg); flex-wrap: wrap;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-top: var(--s-3xl);
  padding: var(--s-3xl) max(var(--s-xl), calc((100vw - var(--maxw)) / 2));
  background-color: var(--jagger);
  background-image:
    radial-gradient(70% 130% at 100% 100%, rgba(255, 180, 220, 0.5), transparent 55%),
    var(--grad-brand);
  border-radius: 0;
  color: #fff;
}
.cta-text { display: flex; flex-direction: column; gap: 5px; }
.cta-text strong { font-size: 22px; font-weight: 800; }
.cta-text span { font-size: 13.5px; color: rgba(255,255,255,0.82); max-width: 52ch; }
.desktop-cta .btn-outline { color: #fff; border-color: rgba(255,255,255,0.5); }
.desktop-cta .btn-outline:hover { background: rgba(255,255,255,0.14); border-color: #fff; }

/* -------------------------------------------------------------- Footer --- */
.site-footer {
  width: 100vw;
  margin-left: calc(50% - 50vw);
  padding: var(--s-2xl) max(var(--s-xl), calc((100vw - var(--maxw)) / 2));
  background: #140528;
  color: rgba(255, 255, 255, 0.68);
}
.footer-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-lg); flex-wrap: wrap;
  padding-bottom: var(--s-lg); border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}
.footer-copy { font-size: 13px; color: rgba(255, 255, 255, 0.68); }
.brand-inline { font-weight: 800; color: #fff; }
.footer-mini-links { display: flex; gap: var(--s-lg); }
.footer-mini-links a { font-size: 13px; color: rgba(255, 255, 255, 0.68); }
.footer-mini-links a:hover { color: var(--pink-bright); }
.footer-sig {
  display: flex; gap: var(--s-lg); margin-top: var(--s-md);
  font-size: 10px; text-transform: uppercase; color: rgba(255, 255, 255, 0.4);
}

/* ============================================ output-panel components ===== */
/* The states JS toggles at runtime: banners, stamps, empty/processing hosts,
   file upload, toasts. (The states.html mockup's page scaffolding lived here
   too; it is design-only and not part of the live app.) */

/* Banners */
.success-banner, .banner-neutral {
  display: flex; align-items: center; gap: var(--s-md);
  padding: var(--s-md) var(--s-lg); border-radius: var(--r-md);
  font-size: 14px; font-weight: 600; margin-bottom: var(--s-lg);
}
.success-banner {
  background: rgba(110,231,163,0.14); color: #2f8f5b;
  border: 1px solid rgba(110,231,163,0.5);
}
.banner-neutral {
  background: var(--chip-bg); color: var(--ink-soft);
  border: 1px solid var(--hairline);
}

/* Editor stamps overlay */
.editor-stamp-host { position: relative; }
.editor-stamp {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%) rotate(-9deg);
  font: 800 26px/1 var(--font-display); letter-spacing: 0.06em; text-transform: uppercase;
  padding: 10px 18px; border-radius: 8px; border: 3px solid currentColor;
  opacity: 0.9; pointer-events: none;
}
.stamp-approved { color: var(--pastel-green); }
.stamp-clean { color: var(--mulled-wine); }

/* Empty / processing hosts */
.empty-host, .processing-host {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  flex: 1; gap: var(--s-md); min-height: 320px;
  border: 1px dashed var(--hairline-2); border-radius: var(--r-md);
  background: #FDFCFA; color: var(--ink-soft); text-align: center; padding: var(--s-xl);
}
.empty-icon { color: var(--hairline-2); }

/* Skeleton loading */
.skeleton-line {
  height: 12px; border-radius: var(--r-pill); margin-bottom: 12px;
  background: linear-gradient(90deg, var(--chip-bg) 25%, rgba(107,26,137,0.12) 37%, var(--chip-bg) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.4s ease infinite;
}
/* Per-line widths come from inline styles in PROCESSING_HTML (app.js). */

/* Redaction preview rows (length-proportional bars) */
.preview-host { padding: var(--s-md) 0; }
.preview-row { display: flex; align-items: center; gap: var(--s-sm); margin-bottom: 12px; }
.preview-bar { height: 14px; border-radius: 3px; background: var(--doc-ink); }
.w-6  { width: 56px; }
.w-7  { width: 76px; }
.w-9  { width: 104px; }
.w-11 { width: 132px; }
.w-14 { width: 176px; }
.preview-caption { font-size: 11px; color: var(--ink-soft); margin-top: var(--s-sm); }

/* File upload */
.file-drop {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--s-sm); min-height: 320px; text-align: center;
  border: 2px dashed var(--hairline-2); border-radius: var(--r-md);
  background: #FDFCFA; padding: var(--s-xl);
  transition: border-color .15s ease, background .15s ease;
}
.file-drop.is-over, .file-drop:hover,
.file-drop:focus-within { border-color: var(--accent); background: var(--chip-bg); }
.file-drop-icon { color: var(--accent); margin-bottom: var(--s-xs); }
.file-drop-headline { font-weight: 700; font-size: 16px; color: var(--violet); }
.file-drop-sub { font-size: 13px; color: var(--ink-soft); }
.file-drop-formats {
  font-size: 11px; color: var(--ink-soft);
  background: var(--chip-bg); padding: 4px 12px; border-radius: var(--r-pill);
  margin-top: var(--s-sm);
}

/* Keep the same height as the drop zone so swapping drop→selected (and the
   tab switch text↔file) doesn't jump the column, especially in the stacked
   one-column layout under 900px. */
.file-selected {
  display: flex; flex-direction: column; justify-content: center;
  min-height: 320px; padding: var(--s-md) 0;
}
.file-selected-card {
  display: flex; align-items: center; gap: var(--s-md);
  padding: var(--s-md) var(--s-lg);
  border: 1px solid var(--hairline); border-radius: var(--r-md);
  background: var(--surface);
}
.file-selected-icon {
  display: grid; place-items: center; width: 40px; height: 40px;
  border-radius: 10px; background: var(--chip-bg); color: var(--accent); flex-shrink: 0;
}
.file-meta { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.file-name {
  font-weight: 700; font-size: 14px; color: var(--violet);
  /* Truncate long filenames instead of letting the card widen the column. */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;
}
.file-size { font-size: 12px; color: var(--ink-soft); }
.file-actions { display: flex; gap: 8px; }
.file-action {
  border: 1px solid var(--hairline-2); background: transparent; cursor: pointer;
  font-size: 12px; font-weight: 700; color: var(--ink-soft);
  padding: 7px 13px; border-radius: var(--r-pill); transition: all .15s ease;
}
.file-action:hover { color: var(--accent); border-color: var(--accent); }

/* Toasts */
.toast {
  display: flex; align-items: center; gap: var(--s-sm);
  padding: var(--s-md) var(--s-lg); border-radius: var(--r-md);
  font-size: 14px; font-weight: 600; margin-bottom: var(--s-md);
  background: var(--grad-ink); color: var(--paper);
  box-shadow: var(--shadow-soft);
}
.toast-danger { background: var(--red-damask); }

/* ---------------------------------------------------------- Animations -- */
@keyframes rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes grow { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes shimmer { from { background-position: 100% 0; } to { background-position: -100% 0; } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .manifesto-strip li, .ledger-row { opacity: 1; }
}

/* ----------------------------------------------------------- Responsive -- */
@media (max-width: 900px) {
  .hero-grid { grid-template-columns: 1fr; gap: var(--s-2xl); }
  .editor-grid { grid-template-columns: 1fr; }
  .top-links { gap: var(--s-md); }
  .top-links a:not(.link-strong):not(.nav-github) { display: none; }
}
@media (max-width: 560px) {
  .top-nav, .hero, .workspace { padding-left: var(--s-md); padding-right: var(--s-md); }
  .manifesto-strip { grid-template-columns: 1fr; }
  .explainer { grid-template-columns: 1fr; }
  .summary-head, .panel-head { flex-direction: column; align-items: flex-start; }
  .summary-help { text-align: left; }
  .ledger-row, .ledger-total { grid-template-columns: 28px 1fr auto; }
  .ledger-bar { grid-column: 1 / -1; }
  /* The total row's caption is a 4th cell with no bar to occupy 1/-1 — without
     this it lands in the 28px first column and stretches the row vertically. */
  .ledger-total .ledger-caption { grid-column: 1 / -1; justify-self: start; }
}
/* ============================================ ui-static: live-app states === */
/* The mockups (ui-design/) hand-code each state; here JS toggles them, so a few
   helpers replace the inline styles states.html used. */

[hidden] { display: none !important; }

/* Off-screen but focusable — the file <input> stays keyboard- and SR-reachable
   (a bare `hidden` drops it from the tab order, leaving the drop zone unusable
   without a mouse). `.file-drop:focus-within` gives it a visible focus ring. */
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Error variant of the output empty-host (Stan 06) — was inline in states.html */
.empty-host.is-error {
  border-style: solid;
  border-color: var(--danger);
  background: var(--danger-soft);
}
.empty-host.is-error .empty-icon,
.empty-host.is-error em { color: var(--danger); }
.readonly-badge.is-error { color: var(--danger); border: 1px solid var(--danger); background: transparent; }

/* Placeholder shown in the summary before the first run */
.ledger-empty {
  font-size: 13px; color: var(--ink-soft);
  padding: var(--s-md) 0 var(--s-lg);
  border-bottom: 1px solid var(--hairline);
}

/* Busy state on the primary button while a request is in flight.
   The `prefers-reduced-motion` block above already stops this via `* { animation: none }`. */
.btn .btn-spin { animation: spin 0.9s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* Copy button confirmation flash */
.copy-floating.is-done { color: #2f8f5b; border-color: rgba(110,231,163,0.7); }

/* Banner sits between the panel head and the editor grid, aligned to panel padding */
.banner-slot:not(:empty) { padding: var(--s-lg) var(--s-xl) 0; }
.banner-slot .success-banner,
.banner-slot .banner-neutral { margin-bottom: 0; }

/* Input foot stacks the counter and the over-limit toast (Stan 05) */
.editor-foot-input { flex-direction: column; align-items: flex-end; gap: var(--s-sm); }
.editor-foot-input .toast { margin-bottom: 0; }
