/* ============================================================
   MELLIO VISUAL LANGUAGE — source of truth
   Extracted from the approved direction mock:
   public/mocks/direction-3b-alive.html (approved 2026-06-10)
   See it living: public/mocks/visual-language.html

   The five rules:
   1. STRUCTURE IN INK, NOT COLOR. Sections and zones are told
      apart by hairlines, short ink tabs, monochrome glyphs and
      the label grammar — never tinted bands, icon tiles, or
      hue-coding.
   2. ONE ACCENT. Data blue carries only real meaning: code,
      notices, the analysis beam, row hover, focus. Green is
      the brand "o" + success, nothing else.
   3. THREE BUTTON ROLES. Primary (ink fill), secondary (white
      + hairline), ghost (text). Any button may carry a
      hand-drawn ink icon; parts of the icon stir on hover.
   4. QUIET AT REST, ALIVE UNDER THE HAND. Life comes from
      motion and material — lifts, shadow blooms, icon stirs,
      the beam — never from hue count.
   5. TWO WRITTEN VOICES. Mono-caps for labels (.mv-cap),
      italic serif for annotations (.mv-ann). Paper content is
      Charter — the export's own face.

   Everything is prefixed (.mv-* / --mv-*) so this file loads
   next to style.css and the app adopts it incrementally.
   Fonts expected: Inter, Newsreader, JetBrains Mono (loaded by
   the app), Charter (system).
   ============================================================ */

:root{
  /* ---- ink scale ---- */
  --mv-ink:#1b1e24;
  --mv-ink-70:rgba(27,30,36,.70);
  --mv-ink-55:rgba(27,30,36,.55);
  --mv-ink-40:rgba(27,30,36,.40);
  --mv-ink-30:rgba(27,30,36,.30);
  --mv-ink-12:rgba(27,30,36,.12);  /* hairlines */
  --mv-ink-08:rgba(27,30,36,.08);  /* section rules */
  --mv-ink-05:rgba(27,30,36,.05);  /* washes */

  /* ---- the accent (rule 2) ---- */
  --mv-blue:#2d4a6e;
  --mv-blue-soft:rgba(45,74,110,.08);
  --mv-blue-mid:rgba(45,74,110,.45);
  --mv-green:#1a4a38;              /* brand "o" + success ONLY */

  /* ---- surfaces ---- */
  --mv-desk:#edeff4;
  --mv-paper:#ffffff;

  /* ---- type ---- */
  --mv-sans:'Inter',system-ui,sans-serif;
  --mv-serif:'Newsreader',Georgia,serif;
  --mv-mono:'JetBrains Mono',ui-monospace,Menlo,monospace;
  --mv-charter:'Charter','Bitstream Charter',Cambria,Georgia,serif;

  /* ---- motion ---- */
  --mv-ease:cubic-bezier(.16,1,.3,1);     /* everything */
  --mv-dock:cubic-bezier(.26,1.1,.35,1);  /* panel docking: slight inertia */
  --mv-t-micro:.18s;   /* hovers on text/ghosts */
  --mv-t-control:.2s;  /* buttons, selects */
  --mv-t-panel:.3s;    /* shadow blooms */
  --mv-t-dock:.42s;    /* docking panels */
  --mv-t-scene:.5s;    /* entrances */

  /* ---- elevation: light follows the hand ---- */
  --mv-shadow-rest:0 1px 2px rgba(20,24,33,.05),0 4px 14px -8px rgba(20,24,33,.12);
  --mv-shadow-lit:0 1px 2px rgba(20,24,33,.05),0 14px 34px -16px rgba(20,24,33,.28);
  --mv-shadow-card:0 1px 2px rgba(20,24,33,.06),0 18px 44px -22px rgba(20,24,33,.25);
  --mv-shadow-pulse:0 1px 2px rgba(20,24,33,.06),0 26px 60px -24px rgba(45,74,110,.4);

  /* ---- radii ---- */
  --mv-r-card:12px;
  --mv-r-panel:10px;
  --mv-r-control:8px;
  --mv-r-btn:6px;
}

/* ============ the desk ============ */
.mv-desk{
  background:var(--mv-desk);
  background-image:radial-gradient(1100px 420px at 50% -80px,rgba(255,255,255,.65),transparent);
}

/* ============ label grammar (rule 5) ============ */
.mv-cap{
  font:600 10px/1 var(--mv-sans);letter-spacing:.13em;
  text-transform:uppercase;color:var(--mv-ink-40);
}
.mv-ann{font-family:var(--mv-serif);font-style:italic;font-size:12.5px;color:var(--mv-ink-40)}
.mv-title{font-family:var(--mv-charter);font-style:italic;font-weight:400;color:var(--mv-ink)}
.mv-tnum{font-variant-numeric:tabular-nums}

/* ============ icons ============
   Hand-drawn inline SVG only — no stock sets. 11–13px box,
   1.5px stroke, currentColor, round caps. Filled dots use
   inline style="fill:currentColor". Moving parts are tagged:
   .stir  — lifts 1.5px on host hover
   .stir2 — shifts right 1.5px on host hover
   .pop   — scales 1.45 on host hover
   Hosts: the three button roles, or any element with .mv-stir. */
svg.mv-i{flex:none;vertical-align:-2px}
svg.mv-i *{
  stroke:currentColor;fill:none;stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round;
  transition:transform .25s var(--mv-ease);
  transform-box:fill-box;transform-origin:center;
}
.mv-btn:hover .mv-i .stir,.mv-ghost:hover .mv-i .stir,.mv-btn-pri:hover .mv-i .stir,.mv-stir:hover .mv-i .stir{transform:translateY(-1.5px)}
.mv-btn:hover .mv-i .stir2,.mv-ghost:hover .mv-i .stir2,.mv-btn-pri:hover .mv-i .stir2,.mv-stir:hover .mv-i .stir2{transform:translateX(1.5px)}
.mv-btn:hover .mv-i .pop,.mv-ghost:hover .mv-i .pop,.mv-btn-pri:hover .mv-i .pop,.mv-stir:hover .mv-i .pop{transform:scale(1.45)}

/* ============ buttons: three roles, nothing else (rule 3) ============ */
.mv-btn-pri,.mv-btn,.mv-ghost{
  font:600 12px/1 var(--mv-sans);cursor:pointer;border:none;
  border-radius:var(--mv-r-btn);white-space:nowrap;user-select:none;
}
.mv-btn-pri{ /* primary — ink fill; lift on hover, press on click */
  padding:8px 16px;background:var(--mv-ink);color:#fff;
  transition:transform .12s var(--mv-ease),box-shadow var(--mv-t-control) var(--mv-ease),background var(--mv-t-control) var(--mv-ease);
}
.mv-btn-pri:hover{transform:translateY(-1px);box-shadow:0 6px 16px -6px rgba(20,24,33,.45)}
.mv-btn-pri:active{transform:translateY(0);box-shadow:none}
.mv-btn{ /* secondary — white, hairline, lifts */
  display:inline-flex;align-items:center;gap:6px;
  padding:7px 12px;background:#fff;color:var(--mv-ink-70);
  box-shadow:inset 0 0 0 1px var(--mv-ink-12),0 1px 2px rgba(20,24,33,.04);
  transition:all var(--mv-t-control) var(--mv-ease);
}
.mv-btn:hover{transform:translateY(-1px);color:var(--mv-ink);box-shadow:inset 0 0 0 1px var(--mv-ink-30),0 4px 12px -4px rgba(20,24,33,.25)}
.mv-btn:active{transform:none}
.mv-btn svg.mv-i{color:var(--mv-ink-55);transition:color var(--mv-t-control) var(--mv-ease)}
.mv-btn:hover svg.mv-i{color:var(--mv-ink)}
.mv-ghost{ /* ghost — text; ink wash on hover */
  display:inline-flex;align-items:center;gap:5px;
  padding:7px 9px;background:none;color:var(--mv-ink-55);
  transition:all var(--mv-t-micro) var(--mv-ease);
}
.mv-ghost:hover{background:var(--mv-ink-05);color:var(--mv-ink)}
.mv-caret{font-size:9px;opacity:.6}
.mv-btn-pri:focus-visible,.mv-btn:focus-visible,.mv-ghost:focus-visible,.mv-sel:focus-visible{
  outline:2px solid var(--mv-blue-mid);outline-offset:2px;
}

/* ============ surfaces & light (rule 4) ============ */
.mv-panel{
  background:#fff;border-radius:var(--mv-r-panel);box-shadow:var(--mv-shadow-rest);
  transition:box-shadow var(--mv-t-panel) var(--mv-ease);
}
.mv-panel:hover,.mv-panel:focus-within{box-shadow:var(--mv-shadow-lit)}
.mv-card{ /* the paper — the document being made */
  background:#fff;border-radius:var(--mv-r-card);position:relative;overflow:hidden;
  box-shadow:var(--mv-shadow-card);
  transition:box-shadow .35s var(--mv-ease);
}
.mv-card.mv-pulse{box-shadow:var(--mv-shadow-pulse)}

/* ============ sections: structure in ink (rule 1) ============
   A hairline crosses the paper; a short 2px ink tab anchors the
   section and reaches further while you work in it. Glyph and
   label ink up under the hand. */
.mv-sec{margin-top:32px}
.mv-sec-head{
  display:flex;align-items:center;gap:9px;flex-wrap:wrap;
  padding:11px 0 6px;border-top:1px solid var(--mv-ink-08);position:relative;
}
.mv-sec-head::before{
  content:"";position:absolute;top:-1px;left:0;width:30px;height:2px;
  background:var(--mv-ink);transition:width .4s var(--mv-ease);
}
.mv-sec:hover .mv-sec-head::before{width:64px}
.mv-sec-head>svg.mv-i{color:var(--mv-ink-55);transition:color .25s var(--mv-ease)}
.mv-sec:hover .mv-sec-head>svg.mv-i{color:var(--mv-ink)}
.mv-sec-head .mv-cap{color:var(--mv-ink-70);font-size:10.5px}
.mv-sec-head .mv-ann{position:relative;top:1px}
.mv-sec-tools{margin-left:auto;display:flex;gap:6px;align-items:center}

/* ============ controls ============ */
.mv-seg{display:inline-flex;background:rgba(27,30,36,.06);border-radius:var(--mv-r-control);padding:2px}
.mv-seg a,.mv-seg button{
  font:600 11px/1 var(--mv-sans);color:var(--mv-ink-40);text-decoration:none;background:none;border:none;cursor:pointer;
  padding:6px 11px;border-radius:6px;transition:all var(--mv-t-control) var(--mv-ease);
}
.mv-seg .on{background:#fff;color:var(--mv-ink);box-shadow:0 1px 3px rgba(20,24,33,.14)}
.mv-sel{ /* a value you can change */
  display:flex;align-items:center;gap:7px;cursor:pointer;font-size:12.5px;
  background:#fff;border-radius:var(--mv-r-control);padding:7px 11px;
  box-shadow:inset 0 0 0 1px var(--mv-ink-12);
  transition:box-shadow var(--mv-t-control) var(--mv-ease),transform .12s var(--mv-ease);
}
.mv-sel:hover{box-shadow:inset 0 0 0 1px var(--mv-blue-mid),0 3px 10px -5px rgba(20,24,33,.3);transform:translateY(-1px)}
.mv-sel .mv-caret{margin-left:auto;color:var(--mv-ink-40)}
.mv-checkrow{display:flex;align-items:center;gap:9px;cursor:pointer;font-size:12.5px;color:var(--mv-ink-70)}
.mv-box{width:13px;height:13px;border:1px solid var(--mv-ink-30);border-radius:4px;flex:none;transition:all .15s var(--mv-ease)}
.mv-checkrow:hover .mv-box{border-color:var(--mv-blue);box-shadow:0 0 0 3px var(--mv-blue-soft)}
.mv-vtype{ /* variable type marker: 123 / Aa — plain, muted */
  display:inline-block;font-family:var(--mv-mono);font-size:9px;
  color:var(--mv-ink-40);position:relative;top:-1px;margin-right:2px;
}

/* ============ notices: the dot/italic voice ============
   Severity lives in the dot (mid = aside, full = active note),
   never in amber bands or red chips. */
.mv-notice{display:flex;gap:9px;align-items:baseline}
.mv-notice .mv-dot{
  width:5px;height:5px;border-radius:50%;background:var(--mv-blue);flex:none;
  animation:mv-notepulse 1.5s var(--mv-ease) .9s 2;
}
.mv-notice.soft .mv-dot{background:var(--mv-blue-mid);animation:none}
.mv-notice p{font-family:var(--mv-serif);font-style:italic;font-size:12.5px;line-height:1.55;color:var(--mv-ink-55);margin:0}
.mv-notice p b{font-style:normal;font-weight:600;font-size:12px;color:var(--mv-ink-70)}
@keyframes mv-notepulse{0%{box-shadow:0 0 0 0 rgba(45,74,110,.4)}100%{box-shadow:0 0 0 7px rgba(45,74,110,0)}}

/* ============ chips & code ============ */
.mv-chip{font-family:var(--mv-mono);font-size:10px;color:var(--mv-ink-55);background:var(--mv-ink-05);border-radius:5px;padding:4px 8px}
.mv-codechip{
  display:inline-block;padding:9px 11px;border-radius:var(--mv-r-control);background:var(--mv-blue-soft);
  font-family:var(--mv-mono);font-size:11px;line-height:1.6;color:var(--mv-ink-70);word-break:break-word;
}
.mv-codechip .fn{color:var(--mv-blue)}

/* ============ paper content (Charter = the export voice) ============ */
.mv-prose{font-family:var(--mv-charter);font-size:15px;line-height:1.7;max-width:64ch;color:var(--mv-ink)}
.mv-prose p{margin:0}
.mv-prose p+p{margin-top:12px}
.mv-frow{display:flex;gap:18px;padding:7px 0;border-bottom:1px solid var(--mv-ink-05);font-size:13px}
.mv-frow:last-child{border-bottom:none}
.mv-frow .k{font-family:var(--mv-charter);font-style:italic;color:var(--mv-ink-55);width:128px;flex:none}
.mv-frow .v{font-family:var(--mv-charter);font-size:14px;color:var(--mv-ink)}
table.mv-apa{
  width:100%;border-collapse:collapse;font-family:var(--mv-charter);
  font-size:13.5px;font-variant-numeric:tabular-nums;
}
table.mv-apa thead tr{border-top:1.5px solid var(--mv-ink);border-bottom:1px solid var(--mv-ink-55)}
table.mv-apa tbody tr:last-child{border-bottom:1.5px solid var(--mv-ink)}
table.mv-apa th{font-weight:400;text-align:right;padding:7px 10px 6px;white-space:nowrap}
table.mv-apa th:first-child,table.mv-apa td:first-child{text-align:left;padding-left:2px}
table.mv-apa td{text-align:right;padding:5.5px 10px;white-space:nowrap}
table.mv-apa tbody tr{transition:background .15s var(--mv-ease)}
table.mv-apa tbody tr:hover{background:var(--mv-blue-soft)}
.mv-tablenote{font-family:var(--mv-charter);font-size:12.5px;line-height:1.6;color:var(--mv-ink-55);max-width:70ch}

/* ============ motion utilities ============ */
/* entrance: the room rises once. Add .mv-rise (+ .d1/.d2/.d3 for
   stagger) to zones; add class "mv-in" to <body> on load. */
.mv-rise{opacity:0;transform:translateY(8px);transition:opacity var(--mv-t-scene) var(--mv-ease),transform var(--mv-t-scene) var(--mv-ease)}
body.mv-in .mv-rise{opacity:1;transform:none}
body.mv-in .mv-rise.d1{transition-delay:.06s}
body.mv-in .mv-rise.d2{transition-delay:.12s}
body.mv-in .mv-rise.d3{transition-delay:.2s}

/* the analysis beam: a .mv-beam div as first child of .mv-card;
   add .run to play (remove, reflow, re-add to replay). */
.mv-beam{
  position:absolute;inset:0;pointer-events:none;opacity:0;
  background:linear-gradient(105deg,transparent 32%,rgba(45,74,110,.12) 50%,transparent 68%);
  transform:translateX(-110%);
}
.mv-beam.run{animation:mv-beam .8s var(--mv-ease) forwards}
@keyframes mv-beam{0%{opacity:1;transform:translateX(-110%)}100%{opacity:1;transform:translateX(110%)}}

/* values settle: wrap changing values in .mv-settle spans; put
   .mv-dim on the container, force a reflow, stagger
   transition-delay per span, then remove .mv-dim.
   CAUTION (hard-learned): the reset state MUST carry
   transition:none + a forced reflow (void el.offsetWidth),
   otherwise the reset and the return ride the same transition
   and the whole animation silently cancels itself. */
.mv-settle{display:inline-block;transition:opacity .45s var(--mv-ease),transform .45s var(--mv-ease)}
.mv-dim .mv-settle{opacity:.12;transform:translateY(3px);transition:none}

/* docking: width on the outer slot, transform+opacity on the
   inner panel, both on --mv-dock for the inertia feel. */
.mv-dock-slot{overflow:hidden;transition:width var(--mv-t-dock) var(--mv-dock)}
.mv-docked .mv-dock-slot{width:0!important}
.mv-dock-panel{transition:transform var(--mv-t-dock) var(--mv-dock),opacity var(--mv-t-panel) var(--mv-ease)}
.mv-docked .mv-dock-panel{transform:translateX(60px);opacity:0}
