/* ============================================================
   golawskimail — motion.css  (production, drop-in after app.css)
   Paper, ink and objects with weight. Nothing bounces.
   Class names match the portal (.thread-row, .row, .nav-pill, .btn,
   .toast, .empty-state, .suggest-chip, .crm-board); new hooks are m-*.
   ============================================================ */

:root {
  /* ---- duration scale (five steps, nothing in between) ---- */
  --t-1:  90ms;   /* touch:    press, hover, caret            */
  --t-2: 160ms;   /* settle:   dot, tick, chip                */
  --t-3: 240ms;   /* move:     toast, roll, page arrive       */
  --t-4: 420ms;   /* travel:   sweep, fold, drop              */
  --t-5: 720ms;   /* ceremony: greeting, illustration, zero   */

  /* ---- easing: every curve stays inside 0..1 (no overshoot) ---- */
  --e-settle: cubic-bezier(.20,.70,.20,1);   /* arriving: fast start, soft landing   */
  --e-leave:  cubic-bezier(.40,0,.80,.60);   /* leaving: gathers speed, exits        */
  --e-move:   cubic-bezier(.45,.05,.20,1);   /* changing place: in-out, decisive     */
  --e-weight: cubic-bezier(.16,1,.30,1);     /* landing with mass: long, heavy tail  */
  --e-ink:    cubic-bezier(.65,0,.35,1);     /* a pen stroke: hesitant start, sure   */
  --e-tick:   steps(3, end);                 /* mechanical: clock hand, segments     */

  --m-stagger: 45ms;
  --m-shadow-lift: 0 1px 0 rgba(43,35,25,.06), 0 10px 18px -14px rgba(43,35,25,.45);
  --m-shadow-held: 0 2px 0 rgba(43,35,25,.05), 0 22px 36px -18px rgba(43,35,25,.55);
  --m-rotate-note: -0.8deg;
}

/* Reduced motion. JS mirrors the media query into data-motion so a user
   choice (Settings → Motion) can override it; this media block is the
   no-JS fallback. Rule: keep opacity fades (≤120ms), drop every transform. */
@media (prefers-reduced-motion: reduce) {
  :root:not([data-motion="full"]) { --t-1: 0ms; --t-2: 120ms; --t-3: 120ms; --t-4: 120ms; --t-5: 120ms; --m-stagger: 0ms; }
}
:root[data-motion="reduce"] { --t-1: 0ms; --t-2: 120ms; --t-3: 120ms; --t-4: 120ms; --t-5: 120ms; --m-stagger: 0ms; }

/* ---------------- 1 · hover lift (rows are sheets of paper) ---------------- */
.row, .thread-row, .m-card {
  transition: background var(--t-2) var(--e-settle), box-shadow var(--t-2) var(--e-settle), transform var(--t-2) var(--e-settle);
}
@media (hover: hover) {
  .row:hover, .thread-row:hover { transform: translateY(-1px); box-shadow: var(--m-shadow-lift); position: relative; z-index: 1; }
  .row:active, .thread-row:active { transform: translateY(0); box-shadow: none; transition-duration: var(--t-1); }
}
:root[data-motion="reduce"] .row:hover, :root[data-motion="reduce"] .thread-row:hover { transform: none; }

/* ---------------- 2 · unread dot settles (ink touching paper) ---------------- */
.unread-dot { position: relative; }
.unread-dot.m-settle { animation: m-dot var(--t-4) var(--e-weight) both; }
.unread-dot.m-settle::after {
  content: ""; position: absolute; inset: -3px; border-radius: 50%;
  border: 1.5px solid currentColor; color: inherit; opacity: 0;
  animation: m-ring var(--t-4) var(--e-settle) both;
}
@keyframes m-dot  { from { transform: scale(.45); opacity: .35; } to { transform: scale(1); opacity: 1; } }
@keyframes m-ring { 0% { transform: scale(.6); opacity: .6; } 100% { transform: scale(1.9); opacity: 0; } }
:root[data-motion="reduce"] .unread-dot.m-settle { animation: m-fade var(--t-2) both; }
:root[data-motion="reduce"] .unread-dot.m-settle::after { display: none; }

/* ---------------- 3/6 · leaving rows (archive sweep, snooze slip) — driven by GM.sweep ---------------- */
.m-leaving { pointer-events: none; }
.m-snooze-hand { transform-origin: 50% 50%; transition: transform calc(var(--t-4) - 60ms) var(--e-tick); }
.m-snoozed .m-snooze-hand { transform: rotate(90deg); }

/* ---------------- 4 · sent mail folds into an envelope ---------------- */
.m-letter { transform-origin: 50% 0; }
.m-envelope { position: fixed; z-index: 60; pointer-events: none; will-change: transform; }
.m-envelope svg { width: 100%; height: 100%; display: block; }
.nav-pill.m-pulse, .m-pulse { animation: m-pulse var(--t-3) var(--e-settle); }
@keyframes m-pulse { 0% { transform: translateY(0); background: var(--accent-wash); } 40% { transform: translateY(-1px); } 100% { transform: translateY(0); } }

/* ---------------- 5/12 · toast as a paper note, with the undo line ---------------- */
.toast, .m-toast {
  transform-origin: 50% 100%;
  animation: m-note-in var(--t-4) var(--e-weight) both;
  box-shadow: var(--m-shadow-lift);
}
.toast.gone, .m-toast.gone { animation: m-note-out var(--t-3) var(--e-leave) forwards; }
@keyframes m-note-in  { from { opacity: 0; transform: translate(-50%, 14px) rotate(var(--m-rotate-note)); } to { opacity: 1; transform: translate(-50%, 0) rotate(0); } }
@keyframes m-note-out { to { opacity: 0; transform: translate(-50%, 8px); } }
.m-line { position: absolute; left: 14px; right: 14px; bottom: 0; height: 2px; border-radius: 2px; background: var(--accent); transform-origin: left center; opacity: .9; }
.m-line.run { animation: m-shrink var(--m-seconds, 10s) linear forwards; }
@keyframes m-shrink { from { transform: scaleX(1); } to { transform: scaleX(0); } }
:root[data-motion="reduce"] .toast, :root[data-motion="reduce"] .m-toast { animation-name: m-fade; }
:root[data-motion="reduce"] .toast.gone, :root[data-motion="reduce"] .m-toast.gone { animation-name: m-fade-out; }
:root[data-motion="reduce"] .m-line { display: none; }

/* ---------------- 7 · deal card picked up, dropped with weight ---------------- */
.m-card { touch-action: none; user-select: none; }
.m-card.m-held {
  position: relative; z-index: 5; cursor: grabbing;
  box-shadow: var(--m-shadow-held);
  transition: box-shadow var(--t-2) var(--e-settle);
}
.m-col.m-over { background: var(--accent-wash); outline: 1px dashed var(--accent); outline-offset: -1px; transition: background var(--t-2), outline-color var(--t-2); }
.m-card.m-landed { animation: m-land var(--t-3) var(--e-weight); }
@keyframes m-land { 0% { box-shadow: var(--m-shadow-held); } 100% { box-shadow: none; } }

/* ---------------- 8 · greeting written in, word by word ---------------- */
.m-greet .w { display: inline-block; opacity: 0; transform: translateY(5px); animation: m-word var(--t-3) var(--e-settle) forwards; animation-delay: calc(var(--i, 0) * 70ms); }
@keyframes m-word { to { opacity: 1; transform: none; } }
.m-greet .m-under { display: block; height: 8px; width: 100%; overflow: visible; margin-top: -2px; }
.m-greet .m-under path { stroke: var(--accent); stroke-width: 2.2; stroke-linecap: round; fill: none; stroke-dasharray: 1; stroke-dashoffset: 1; animation: m-draw-unit var(--t-5) var(--e-ink) forwards; animation-delay: calc(var(--n, 3) * 70ms); }
@keyframes m-draw-unit { to { stroke-dashoffset: 0; } }
:root[data-motion="reduce"] .m-greet .w { transform: none; animation-name: m-fade; animation-delay: 0ms; }
:root[data-motion="reduce"] .m-greet .m-under path { animation: none; stroke-dashoffset: 0; }

/* ---------------- 9/15 · illustrations draw themselves (GM.draw sets dasharray per path) ---------------- */
.m-illo { width: 160px; height: 120px; display: block; margin: 0 auto 10px; color: var(--text); overflow: visible; }
.m-illo path { fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.m-illo .fill { stroke: none; opacity: 0; transition: opacity var(--t-4) var(--e-settle); }
.m-illo.m-drawn .fill { opacity: 1; }
.m-illo .fill.clay  { fill: var(--accent); opacity: 0; }  .m-illo.m-drawn .fill.clay  { opacity: .22; }
.m-illo .fill.moss  { fill: var(--good); }                .m-illo.m-drawn .fill.moss  { opacity: .32; }
.m-illo .fill.ochre { fill: var(--warn); }                .m-illo.m-drawn .fill.ochre { opacity: .28; }
.m-illo .fill.paper { fill: var(--bg-raised); }           .m-illo.m-drawn .fill.paper { opacity: 1; }
.m-illo .faint { opacity: .45; }
.empty-state .title, .empty-state .desc, .empty-state .btn { animation: m-word var(--t-4) var(--e-settle) both; opacity: 0; transform: translateY(5px); }
.empty-state .desc { animation-delay: 90ms; } .empty-state .btn { animation-delay: 180ms; }
.empty-state.m-zero .title { font-size: var(--fs-lg); }
:root[data-motion="reduce"] .empty-state .title, :root[data-motion="reduce"] .empty-state .desc, :root[data-motion="reduce"] .empty-state .btn { transform: none; animation-name: m-fade; animation-delay: 0ms; }

/* ---------------- 10 · "Sending and receiving" status bar (OE98, modernised) ---------------- */
.m-status { display: flex; flex-direction: column; gap: 8px; padding: 10px 14px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--bg-raised); font-size: var(--fs-sm); }
.m-status .m-status-top { display: flex; align-items: center; gap: 8px; color: var(--text-dim); }
.m-status .m-arrows { display: inline-flex; gap: 2px; width: 18px; }
.m-status .m-arrows i { display: block; width: 7px; height: 10px; background: currentColor; opacity: .25; clip-path: polygon(50% 0, 100% 45%, 70% 45%, 70% 100%, 30% 100%, 30% 45%, 0 45%); }
.m-status .m-arrows i:last-child { transform: rotate(180deg); }
.m-status.m-busy.recv .m-arrows i:last-child, .m-status.m-busy.sendg .m-arrows i:first-child { opacity: 1; color: var(--accent); animation: m-blink 900ms var(--e-tick) infinite; }
@keyframes m-blink { 50% { opacity: .35; } }
.m-bar { display: grid; grid-auto-flow: column; gap: 3px; height: 10px; }
.m-bar i { display: block; border-radius: 2px; background: var(--line-soft); transition: background var(--t-2) var(--e-settle), transform var(--t-2) var(--e-weight); transform: scaleY(.6); }
.m-bar i.on { background: var(--accent); transform: scaleY(1); }
.m-status.m-indeterminate .m-bar i { animation: m-seg 1400ms var(--e-move) infinite; animation-delay: calc(var(--i) * 80ms); }
@keyframes m-seg { 0%, 100% { background: var(--line-soft); } 30% { background: var(--accent); } }
.m-status .m-status-text { font-variant-numeric: tabular-nums; }
.m-status.done { color: var(--good); }
:root[data-motion="reduce"] .m-bar i { transition: none; transform: none; }
:root[data-motion="reduce"] .m-status.m-indeterminate .m-bar i { animation: none; background: var(--accent-wash); }
:root[data-motion="reduce"] .m-status .m-arrows i { animation: none; }

/* ---------------- 11 · composer focus glow (a desk lamp, not a neon) ---------------- */
.rte, .input, textarea.input { transition: box-shadow var(--t-3) var(--e-settle), border-color var(--t-3) var(--e-settle); }
.rte:focus-within, .input:focus { border-color: var(--text-dim); box-shadow: 0 0 0 3px var(--accent-wash), 0 0 24px -8px var(--accent); outline: none; }
.rte.m-typing, .input.m-typing { box-shadow: 0 0 0 3px var(--accent-wash), 0 0 32px -6px var(--accent); }
.rte-area, .input { caret-color: var(--accent); }

/* ---------------- 13 · skeleton shimmer, earthy ---------------- */
.m-skel { position: relative; overflow: hidden; border-radius: 6px; background: var(--line-soft); min-height: 12px; }
.m-skel::after { content: ""; position: absolute; inset: 0; transform: translateX(-100%); background: linear-gradient(90deg, transparent 0, var(--bg-raised) 45%, var(--warn-wash) 55%, transparent 100%); animation: m-shimmer 1800ms var(--e-move) infinite; }
@keyframes m-shimmer { to { transform: translateX(100%); } }
:root[data-motion="reduce"] .m-skel::after { animation: none; }

/* ---------------- 14 · AI suggestions as handwritten chips ---------------- */
.suggest-chip, .m-chip {
  font-family: "Segoe Print", "Bradley Hand", Noteworthy, "Iowan Old Style", Palatino, Georgia, serif; font-style: italic;
  border-radius: 255px 15px 225px 15px / 15px 225px 15px 255px;   /* the hand-drawn border trick */
  border: 1.5px solid var(--line); background: var(--bg-raised); color: var(--text);
  transition: border-color var(--t-2) var(--e-settle), transform var(--t-2) var(--e-settle), background var(--t-2);
}
.suggest-chip:nth-child(odd), .m-chip:nth-child(odd) { transform: rotate(-.6deg); }
.suggest-chip:nth-child(even), .m-chip:nth-child(even) { transform: rotate(.4deg); }
.suggest-chip:hover, .m-chip:hover { border-color: var(--accent); color: var(--accent); transform: rotate(0) translateY(-1px); }
.m-chips .m-chip { opacity: 0; animation: m-chip var(--t-3) var(--e-settle) forwards; animation-delay: calc(var(--i, 0) * var(--m-stagger)); }
@keyframes m-chip { from { opacity: 0; translate: 0 4px; rotate: -2deg; } to { opacity: 1; translate: 0 0; rotate: 0deg; } }
:root[data-motion="reduce"] .m-chips .m-chip { animation-name: m-fade; }
:root[data-motion="reduce"] .suggest-chip, :root[data-motion="reduce"] .m-chip { transform: none; }

/* ---------------- 16 · button press (a key, not a sponge) ---------------- */
.btn { transition: transform var(--t-1) var(--e-settle), box-shadow var(--t-1), background var(--t-2), border-color var(--t-2); }
.btn:active { transform: translateY(1px); box-shadow: none; }
:root[data-motion="reduce"] .btn:active { transform: none; }

/* ---------------- 17 · nav: the ink mark grows beside the active section ---------------- */
.nav-pill { position: relative; }
.nav-pill.active::before { content: ""; position: absolute; left: 0; top: 9px; bottom: 9px; width: 3px; border-radius: 2px; background: var(--accent); transform-origin: 50% 50%; animation: m-mark var(--t-3) var(--e-settle) both; }
@keyframes m-mark { from { transform: scaleY(0); } }
:root[data-motion="reduce"] .nav-pill.active::before { animation: none; }

/* ---------------- 18 · checkbox tick drawn with a pen ---------------- */
.m-check { position: relative; display: inline-grid; place-items: center; width: 18px; height: 18px; border: 1.5px solid var(--text-dim); border-radius: 5px; background: var(--bg-raised); cursor: pointer; transition: border-color var(--t-2), background var(--t-2); }
.m-check input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.m-check svg { width: 14px; height: 14px; }
.m-check svg path { fill: none; stroke: var(--accent-text-on); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 20; stroke-dashoffset: 20; transition: stroke-dashoffset var(--t-2) var(--e-ink); }
.m-check:has(input:checked) { background: var(--accent); border-color: var(--accent); }
.m-check:has(input:checked) svg path { stroke-dashoffset: 0; }
.m-check:has(input:focus-visible) { box-shadow: 0 0 0 3px var(--accent-wash); }

/* ---------------- 19 · rubber stamp ---------------- */
.m-stamp { position: absolute; right: 12px; top: 8px; padding: 2px 8px; border: 2px solid var(--good); color: var(--good); border-radius: 4px; font-weight: 700; font-size: 11px; letter-spacing: .14em; text-transform: uppercase; transform: rotate(-7deg); opacity: .92; mix-blend-mode: multiply; pointer-events: none; animation: m-stamp var(--t-3) var(--e-weight) both; }
.m-stamp.bad { border-color: var(--bad); color: var(--bad); }
:root[data-theme="dark"] .m-stamp { mix-blend-mode: screen; }
@keyframes m-stamp { from { opacity: 0; transform: rotate(-7deg) scale(1.5); } to { opacity: .92; transform: rotate(-7deg) scale(1); } }
:root[data-motion="reduce"] .m-stamp { animation-name: m-fade; }

/* ---------------- 20 · page turn (MPA view transitions + first-paint settle) ---------------- */
@view-transition { navigation: auto; }
::view-transition-old(root) { animation: m-fade-out var(--t-2) var(--e-leave) both; }
::view-transition-new(root) { animation: m-arrive var(--t-3) var(--e-settle) both; }
@keyframes m-arrive { from { opacity: 0; transform: translateY(4px); } }
.content > .card, .content > .row-list, .content > .empty-state { animation: m-arrive var(--t-3) var(--e-settle) both; }
.content > :nth-child(2) { animation-delay: var(--m-stagger); } .content > :nth-child(3) { animation-delay: calc(2 * var(--m-stagger)); }
.content > :nth-child(4) { animation-delay: calc(3 * var(--m-stagger)); } .content > :nth-child(n+5) { animation-delay: calc(4 * var(--m-stagger)); }
:root[data-motion="reduce"]::view-transition-new(root), :root[data-motion="reduce"] .content > * { animation-name: m-fade; }

/* ---------------- 21 · health checks tick in sequence ---------------- */
.m-checks .m-tick { width: 16px; height: 16px; flex: none; }
.m-checks .m-tick circle { fill: none; stroke: var(--line); stroke-width: 1.5; }
.m-checks .m-tick path { fill: none; stroke: var(--good); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.m-checks .m-all { opacity: 0; transition: opacity var(--t-4) var(--e-settle); color: var(--good); }
.m-checks.m-done .m-all { opacity: 1; }

/* ---------------- 22 · numbers roll like a counter ---------------- */
.m-roll { display: inline-grid; overflow: hidden; vertical-align: bottom; font-variant-numeric: tabular-nums; }
.m-roll > span { grid-area: 1 / 1; }

/* ---------------- shared ---------------- */
@keyframes m-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes m-fade-out { to { opacity: 0; } }

/* =====================================================================
   Aero re-skin (reports/rebrand/b-aero): light and floaty. A sheen sweeps
   instead of an ink stroke drawing; rows and cards settle with a slight
   overshoot. Arrivals are transform-only, never opacity, so a throttled
   animation clock (background tab, headless capture) cannot leave content
   invisible. Everything below is cancelled by reduced motion.
   ===================================================================== */
:root { --e-float: cubic-bezier(.26,1.1,.32,1); --m-rotate-note: 0deg; }
@keyframes aero-rise { from { transform: translateY(8px) scale(.98); } to { transform: none; } }
@keyframes bubble-in { 0% { transform: translateY(10px) scale(.85); } 70% { transform: translateY(-1px) scale(1.03); } 100% { transform: none; } }
@keyframes sheen-sweep { from { background-position: -140% 0; } to { background-position: 240% 0; } }
@keyframes m-arrive { from { transform: translateY(6px); } }

.thread-scroll > .thread-row, .crm-col .deal { animation: aero-rise var(--t-4) var(--e-float) both; }
.thread-scroll > .thread-row:nth-child(2), .crm-col .deal:nth-child(2) { animation-delay: 40ms; }
.thread-scroll > .thread-row:nth-child(3), .crm-col .deal:nth-child(3) { animation-delay: 80ms; }
.thread-scroll > .thread-row:nth-child(4), .crm-col .deal:nth-child(4) { animation-delay: 120ms; }
.thread-scroll > .thread-row:nth-child(n+5), .crm-col .deal:nth-child(n+5) { animation-delay: 160ms; }
.note { animation: bubble-in var(--t-5) var(--e-float) both; }
.m-greet .w { opacity: 1; animation-name: aero-rise; animation-timing-function: var(--e-float); }
.m-greet .m-under path { stroke: var(--azure); }
.greet h1.m-greet .w { background: linear-gradient(100deg, var(--ink) 40%, var(--azure-deep) 50%, var(--ink) 60%); background-size: 260% 100%;
  -webkit-background-clip: text; background-clip: text; animation: aero-rise var(--t-3) var(--e-float) both, sheen-sweep 2.6s var(--e-settle) 1 both; animation-delay: calc(var(--i, 0) * 70ms), 300ms; }
.greet h1.m-greet .w.n { background-image: linear-gradient(100deg, var(--azure-deep) 40%, var(--leaf) 50%, var(--azure-deep) 60%); }
@supports not ((background-clip: text) or (-webkit-background-clip: text)) { .greet h1.m-greet .w { background: none; } }
.empty-state .title, .empty-state .desc, .empty-state .btn { opacity: 1; animation-name: aero-rise; }
@media (max-width: 899px) { .toast, .m-toast { animation-name: aero-rise; } }
.m-illo { color: var(--azure-deep); }
.m-illo .fill.clay { fill: var(--azure); } .m-illo .fill.moss { fill: var(--leaf); } .m-illo .fill.ochre { fill: var(--sun); }
.nav-pill.active::before { display: none; }

:root[data-motion="reduce"] .thread-scroll > .thread-row, :root[data-motion="reduce"] .crm-col .deal, :root[data-motion="reduce"] .note,
:root[data-motion="reduce"] .m-greet .w, :root[data-motion="reduce"] .empty-state .title, :root[data-motion="reduce"] .empty-state .desc,
:root[data-motion="reduce"] .empty-state .btn, :root[data-motion="reduce"] .content > * { animation: none !important; }
@media (prefers-reduced-motion: reduce) {
  :root:not([data-motion="full"]) .thread-scroll > .thread-row, :root:not([data-motion="full"]) .crm-col .deal, :root:not([data-motion="full"]) .note,
  :root:not([data-motion="full"]) .m-greet .w, :root:not([data-motion="full"]) .empty-state .title, :root:not([data-motion="full"]) .empty-state .desc,
  :root:not([data-motion="full"]) .empty-state .btn, :root:not([data-motion="full"]) .content > * { animation: none !important; }
}
