/* ==========================================================================
   FollowSort design system
   Source of truth: design-system/followsort/MASTER.md
   Layers: 1 tokens · 2 base · 3 layout · 4 type · 5 controls · 6 components
   ========================================================================== */

/* --- 1. TOKENS ---------------------------------------------------------- */
:root{
  /* surfaces: 0 = page, 1 = raised panel, 2 = card/input on top of a panel */
  --surface-0:#f5f4ef; --surface-1:#faf9f6; --surface-2:#ffffff;

  /* text — all pass 4.5:1 on surface-2 (the lightest surface, worst case) */
  --text-primary:#1a1a18;     /* 16.4:1 */
  --text-secondary:#52514e;   /*  7.9:1 */
  --text-muted:#6e6c66;       /*  5.2:1 — was #898781 (3.3:1, failed AA) */

  --text-accent:#4a3aa7; --bg-accent:#eeedfe;
  --text-success:#0f6e56; --bg-success:#e1f5ee;
  --text-warning:#854f0b; --bg-warning:#faeeda;
  --text-danger:#b3261e;  --bg-danger:#fdecea;   /* errors, distinct from warning */

  --border:rgba(0,0,0,0.12); --border-strong:rgba(0,0,0,0.20); --border-accent:#7f77dd;
  --fill-accent:#5546c9;      /* 6.7:1 against --on-accent */
  --on-accent:#ffffff;
  --ring:#5546c9;

  /* space — density 6/10 (standard): 4 → 64 */
  --space-1:4px; --space-2:8px; --space-3:12px; --space-4:16px;
  --space-5:24px; --space-6:32px; --space-7:48px; --space-8:64px;

  /* type */
  --font:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --fs-xs:13px; --fs-sm:14px; --fs-base:15px; --fs-md:17px;
  --fs-lg:20px; --fs-xl:22px; --fs-2xl:clamp(24px,5.5vw,30px);
  --lh-tight:1.3; --lh-body:1.6;

  /* shape + motion */
  --radius:8px; --radius-lg:12px; --radius-pill:999px;
  --dur-fast:150ms; --dur:220ms; --ease:cubic-bezier(0.16,1,0.3,1);
}
@media (prefers-color-scheme:dark){:root{
  --surface-0:#1a1a19; --surface-1:#222220; --surface-2:#2a2a28;
  --text-primary:#f5f5f0;
  --text-secondary:#c3c2b7;
  --text-muted:#9a988f;       /* 5.0:1 on surface-2 — was #898781 (4.5:1 borderline) */
  --text-accent:#afa9ec; --bg-accent:#2e2861;
  --text-success:#5dcaa5; --bg-success:#0f3d31;
  --text-warning:#f0b060; --bg-warning:#3d2e14;
  --text-danger:#ffb4ab;  --bg-danger:#3d1512;
  --border:rgba(255,255,255,0.14); --border-strong:rgba(255,255,255,0.22); --border-accent:#7f77dd;
  --fill-accent:#6f63d6; --on-accent:#ffffff; --ring:#a79dee;
}}

/* --- 2. BASE ------------------------------------------------------------ */
*{box-sizing:border-box;}
html{-webkit-text-size-adjust:100%;}
body{margin:0;background:var(--surface-0);color:var(--text-primary);
  font-family:var(--font);font-size:16px;line-height:1.5;-webkit-font-smoothing:antialiased;
  overflow-wrap:break-word;}
a{color:inherit;}
p{margin:0;}
img,svg{max-width:100%;}

/* One focus treatment for every control. :focus-visible keeps it off mouse clicks
   but guarantees keyboard users always see where they are. */
:focus-visible{outline:2px solid var(--ring);outline-offset:2px;border-radius:2px;}
:focus:not(:focus-visible){outline:none;}

.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0;}
.skip-link{position:absolute;left:var(--space-3);top:-100px;z-index:10;
  background:var(--fill-accent);color:var(--on-accent);padding:10px 16px;
  border-radius:var(--radius);font-size:var(--fs-sm);text-decoration:none;}
.skip-link:focus{top:var(--space-3);}

/* --- 3. LAYOUT ---------------------------------------------------------- */
.wrap{max-width:720px;margin:0 auto;padding:var(--space-5) var(--space-4) var(--space-7);}
.card{background:var(--surface-1);border-radius:var(--radius-lg);padding:var(--space-7) var(--space-6);}

.site-head{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);
  margin-bottom:var(--space-5);}
.brand{display:inline-flex;align-items:center;gap:var(--space-2);text-decoration:none;
  font-size:var(--fs-base);font-weight:600;letter-spacing:-0.01em;color:var(--text-primary);
  padding:var(--space-2);margin:calc(var(--space-2) * -1);border-radius:var(--radius);}
.brand svg{width:20px;height:20px;color:var(--fill-accent);flex-shrink:0;}
.site-foot{margin-top:var(--space-7);padding-top:var(--space-4);
  border-top:1px solid var(--border);color:var(--text-muted);font-size:var(--fs-xs);text-align:center;}

.page-head{display:flex;align-items:flex-start;justify-content:space-between;
  flex-wrap:wrap;gap:var(--space-3);}
.stack{display:grid;gap:var(--space-3);}
.center{text-align:center;}
.muted{color:var(--text-muted);}
.sec{color:var(--text-secondary);}

/* --- 4. TYPE ------------------------------------------------------------ */
.hero-title{font-size:var(--fs-2xl);font-weight:600;line-height:var(--lh-tight);
  letter-spacing:-0.02em;margin:0 auto var(--space-3);max-width:26ch;}
.hero-sub{font-size:var(--fs-base);color:var(--text-secondary);line-height:var(--lh-body);
  margin:0 auto var(--space-5);max-width:36ch;}
.page-title{font-size:var(--fs-xl);font-weight:600;letter-spacing:-0.01em;margin:0;}
.page-sub{font-size:var(--fs-sm);color:var(--text-secondary);margin:var(--space-1) 0 0;}
.panel-title{font-size:var(--fs-md);font-weight:600;margin:var(--space-3) 0 var(--space-1);}
.body-sm{font-size:var(--fs-sm);color:var(--text-secondary);line-height:var(--lh-body);margin:0;}
.note{font-size:var(--fs-xs);color:var(--text-muted);margin:0;}
.inline-note{display:flex;align-items:center;justify-content:center;gap:6px;
  font-size:var(--fs-xs);color:var(--text-secondary);margin:var(--space-4) 0 0;}
.link-row{font-size:var(--fs-xs);margin:var(--space-3) 0 0;}
.h2{font-size:var(--fs-base);font-weight:600;margin:var(--space-6) 0 var(--space-3);}

/* Errors are announced (role="alert") and shown in the danger tone, not warning. */
.form-error{display:none;background:var(--bg-danger);color:var(--text-danger);
  font-size:var(--fs-xs);line-height:1.5;padding:var(--space-2) var(--space-3);
  border-radius:var(--radius);margin:var(--space-3) auto 0;max-width:440px;text-align:left;}
.form-error[data-shown]{display:block;}

/* --- 5. CONTROLS -------------------------------------------------------- */
.field{display:grid;gap:6px;text-align:left;flex:1;min-width:0;}
.field > label{font-size:var(--fs-xs);color:var(--text-secondary);font-weight:500;}
.field-affix{position:relative;}
.field-affix > .affix{position:absolute;left:12px;top:50%;transform:translateY(-50%);
  font-size:var(--fs-base);color:var(--text-muted);pointer-events:none;}
.field-affix > input{padding-left:28px;}
.field-affix--icon > .affix{font-size:16px;}
.field-affix--icon > input{padding-left:36px;}

input{width:100%;height:44px;border:1px solid var(--border-strong);border-radius:var(--radius);
  background:var(--surface-2);color:var(--text-primary);padding:0 12px;
  font-size:16px;font-family:inherit;   /* 16px: anything smaller makes iOS Safari zoom on focus */
  transition:border-color var(--dur-fast) var(--ease);}
input::placeholder{color:var(--text-muted);}
input:hover{border-color:var(--border-accent);}

.btn{min-height:44px;padding:0 20px;border:none;border-radius:var(--radius);background:var(--fill-accent);
  color:var(--on-accent);font-size:var(--fs-base);font-weight:500;font-family:inherit;cursor:pointer;
  display:inline-flex;align-items:center;justify-content:center;gap:6px;white-space:nowrap;
  text-decoration:none;transition:background var(--dur-fast) var(--ease),transform var(--dur-fast) var(--ease);}
.btn:hover{background:color-mix(in srgb,var(--fill-accent) 88%,#000);}
.btn:active{transform:scale(0.98);}
.btn[disabled]{opacity:0.55;cursor:default;transform:none;}
.btn-lg{min-height:48px;padding:0 28px;font-size:var(--fs-md);gap:8px;}
.btn-sec{min-height:44px;padding:0 14px;border:1px solid var(--border-strong);background:var(--surface-2);
  color:var(--text-primary);border-radius:var(--radius);font-size:var(--fs-sm);font-weight:500;
  font-family:inherit;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;
  gap:6px;text-decoration:none;white-space:nowrap;
  transition:background var(--dur-fast) var(--ease),border-color var(--dur-fast) var(--ease);}
.btn-sec:hover{background:var(--surface-1);border-color:var(--border-accent);}

/* Text-styled control that is genuinely a <button> — keyboard + AT reachable. */
.linkbtn{background:none;border:none;padding:var(--space-2);margin:calc(var(--space-2) * -1);
  font:inherit;font-size:inherit;color:var(--text-secondary);text-decoration:underline;
  text-underline-offset:2px;cursor:pointer;}
.linkbtn:hover{color:var(--text-primary);}

/* Hero + recovery forms: the field keeps at least 200px, so on a 375px screen
   the submit button wraps to its own full-width line instead of being squeezed. */
.form-inline{display:flex;gap:var(--space-2);align-items:flex-end;flex-wrap:wrap;
  max-width:440px;margin:0 auto;}
.form-inline .field{flex:1 1 200px;}
.form-inline .btn{flex:1 1 auto;}
/* Disclosure: animating grid-template-rows 0fr->1fr gives a real height
   transition without hardcoding a pixel height. visibility keeps the collapsed
   fields out of the tab order, and is delayed on close so the collapse is seen. */
.form-stack{display:grid;grid-template-rows:0fr;max-width:440px;margin:0 auto;
  opacity:0;visibility:hidden;
  transition:grid-template-rows var(--dur) var(--ease),opacity var(--dur) var(--ease),
             visibility 0s linear var(--dur);}
.form-stack[data-open]{grid-template-rows:1fr;opacity:1;visibility:visible;
  transition:grid-template-rows var(--dur) var(--ease),opacity var(--dur) var(--ease),
             visibility 0s;}
.form-stack-inner{min-height:0;overflow:hidden;display:grid;gap:var(--space-3);
  padding-top:var(--space-3);}
.form-stack .pair{display:flex;gap:var(--space-2);flex-wrap:wrap;}
.form-stack .pair .field{flex:1 1 180px;}

/* --- 6. COMPONENTS ------------------------------------------------------ */

/* chips */
.chip{display:inline-flex;align-items:center;border-radius:var(--radius-pill);padding:7px 13px;
  font-size:var(--fs-xs);font-family:inherit;line-height:1.2;
  background:var(--surface-2);border:1px solid var(--border);color:var(--text-secondary);}
.chip--accent{background:var(--bg-accent);color:var(--text-accent);border-color:transparent;}
.chip--success{background:var(--bg-success);color:var(--text-success);border-color:transparent;}
.chip--muted{background:var(--surface-1);color:var(--text-secondary);border-color:transparent;}
.chip--dashed{border:1px dashed var(--border-strong);color:var(--text-muted);background:var(--surface-2);}
.chip-row{display:flex;flex-wrap:wrap;gap:var(--space-2);}
.chip-btn{cursor:pointer;transition:background var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease);}
.chip-btn:hover{border-color:var(--border-accent);}
.chip-btn[aria-pressed="true"]{background:var(--fill-accent);color:var(--on-accent);border-color:transparent;}
/* Touch devices get the 44px minimum; pointer devices keep the denser filter row. */
@media (pointer:coarse){.chip-btn{min-height:44px;padding-left:16px;padding-right:16px;}}

/* stat tiles */
.stat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:var(--space-2);}
.stat{background:var(--surface-1);border-radius:var(--radius);padding:var(--space-3) var(--space-3);}
.stat .k{font-size:var(--fs-xs);color:var(--text-secondary);margin:0;}
.stat .v{font-size:var(--fs-xl);font-weight:600;margin:2px 0 0;font-variant-numeric:tabular-nums;}

/* account rows */
.acct{display:flex;align-items:center;gap:var(--space-3);background:var(--surface-2);
  border:1px solid var(--border);border-radius:var(--radius-lg);padding:var(--space-3) var(--space-3);
  min-width:0;}
.avatar{width:42px;height:42px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  font-weight:600;font-size:var(--fs-sm);flex-shrink:0;background:var(--surface-1);color:var(--text-secondary);}
.avatar--accent{background:var(--bg-accent);color:var(--text-accent);}
.avatar--success{background:var(--bg-success);color:var(--text-success);}
.avatar--muted{background:var(--surface-1);color:var(--text-secondary);}
.acct-body{min-width:0;flex:1;}
/* Nested flex rows need their own min-width:0 — otherwise a long name or handle
   sets a min-content floor that widens the card and scrolls the whole page. */
.acct-title{display:flex;align-items:center;gap:var(--space-2);min-width:0;}
.acct-title .ti{flex-shrink:0;}   /* verified badge must not be squashed by a long name */
.acct-name{font-size:var(--fs-base);font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.acct-handle{font-size:var(--fs-xs);color:var(--text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.acct-bio{font-size:var(--fs-xs);color:var(--text-secondary);margin:2px 0 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.cat{font-size:12px;background:var(--surface-1);color:var(--text-secondary);padding:4px 10px;
  border-radius:var(--radius-pill);flex-shrink:0;white-space:nowrap;}
/* Icon-only link: 18px glyph, 44px hit area, negative margin so the row stays dense. */
.acct-link{color:var(--text-muted);flex-shrink:0;display:inline-flex;align-items:center;
  justify-content:center;width:44px;height:44px;margin:-13px -10px -13px 0;border-radius:var(--radius);
  transition:color var(--dur-fast) var(--ease),background var(--dur-fast) var(--ease);}
.acct-link:hover{color:var(--text-primary);background:var(--surface-1);}
/* minmax(0,1fr), not the default 1fr: grid tracks otherwise refuse to shrink
   below their items' min-content width, which is what pushed cards off-screen. */
.rows{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--space-2);}

/* progress + spinner */
.progress{height:8px;background:var(--surface-2);border:1px solid var(--border);
  border-radius:var(--radius-pill);overflow:hidden;}
.progress > .bar{height:100%;background:var(--fill-accent);transition:width .5s var(--ease);}
@keyframes spin{to{transform:rotate(360deg);}}
.spin{animation:spin 1.1s linear infinite;}
.disc{display:inline-flex;align-items:center;justify-content:center;width:52px;height:52px;
  border-radius:50%;background:var(--bg-accent);}

/* trust strip */
.trust{display:flex;justify-content:center;gap:var(--space-5);flex-wrap:wrap;list-style:none;
  margin:var(--space-6) 0 0;padding:var(--space-5) 0 0;border-top:1px solid var(--border);}
.trust > li{display:flex;align-items:center;gap:var(--space-2);font-size:var(--fs-xs);
  color:var(--text-secondary);}
.trust .ti{font-size:18px;color:var(--text-muted);}

/* paywall */
.blur{filter:blur(3px);opacity:0.55;pointer-events:none;}
.lock-panel{background:var(--surface-2);border:1px solid var(--border-strong);border-radius:var(--radius-lg);
  padding:var(--space-5);text-align:center;margin-top:var(--space-4);}
.banner{display:flex;align-items:center;gap:var(--space-2);background:var(--bg-warning);
  border-radius:var(--radius);padding:10px 14px;color:var(--text-warning);font-size:var(--fs-xs);}
.skeleton-line{height:12px;background:var(--surface-1);border-radius:4px;}

/* long-form prose (privacy, terms) */
.prose{max-width:68ch;margin:0 auto;}
.prose h1{font-size:var(--fs-xl);font-weight:600;letter-spacing:-0.01em;margin:0 0 var(--space-1);}
.prose .updated{font-size:var(--fs-xs);color:var(--text-muted);margin:0 0 var(--space-6);}
.prose h2{font-size:var(--fs-md);font-weight:600;color:var(--text-primary);
  margin:var(--space-6) 0 var(--space-3);}
.prose h3{font-size:var(--fs-base);font-weight:600;color:var(--text-primary);
  margin:var(--space-5) 0 var(--space-2);}
.prose p,.prose li{font-size:var(--fs-sm);line-height:var(--lh-body);color:var(--text-secondary);}
.prose p{margin:0 0 var(--space-3);}
.prose ul{margin:0 0 var(--space-4);padding-left:1.2rem;}
.prose li{margin-bottom:var(--space-2);}
.prose strong{color:var(--text-primary);font-weight:600;}
.prose a{color:var(--text-accent);}
.prose .lead{font-size:var(--fs-base);color:var(--text-primary);}
.prose table{width:100%;border-collapse:collapse;font-size:var(--fs-xs);margin:0 0 var(--space-4);}
.prose th{text-align:left;font-weight:600;color:var(--text-primary);
  padding:var(--space-2) 10px var(--space-2) 0;border-bottom:1px solid var(--border);}
.prose td{padding:var(--space-2) 10px var(--space-2) 0;border-bottom:1px solid var(--border);
  color:var(--text-secondary);vertical-align:top;}
/* Unfilled legal placeholder — deliberately loud so it cannot ship unnoticed. */
.todo{background:var(--bg-warning);color:var(--text-warning);padding:1px 6px;
  border-radius:4px;font-weight:600;font-size:0.95em;}
.legal-nav{display:flex;gap:var(--space-4);justify-content:center;flex-wrap:wrap;
  margin-top:var(--space-6);padding-top:var(--space-4);border-top:1px solid var(--border);
  font-size:var(--fs-xs);}

/* admin */
.metric-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:var(--space-2);}
.metric{background:var(--surface-1);border:1px solid var(--border);border-radius:var(--radius);
  padding:var(--space-3) var(--space-4);}
.metric .k{font-size:12px;color:var(--text-secondary);margin:0;}
.metric .v{font-size:24px;font-weight:600;margin:var(--space-1) 0 0;font-variant-numeric:tabular-nums;}
.metric--hero{background:var(--bg-accent);border-color:transparent;}
.metric--hero .v{font-size:34px;color:var(--text-accent);}
.table{width:100%;border-collapse:collapse;font-size:var(--fs-xs);}
.table th{text-align:left;color:var(--text-muted);font-weight:600;padding:var(--space-2) 10px;
  border-bottom:1px solid var(--border);}
.table td{padding:var(--space-2) 10px;border-bottom:1px solid var(--border);color:var(--text-secondary);}
.table .num{text-align:right;font-variant-numeric:tabular-nums;}
.svgwrap{width:100%;overflow-x:auto;}
.funnel-row{display:flex;align-items:center;gap:var(--space-3);}
.funnel-row .lbl{width:120px;font-size:var(--fs-xs);color:var(--text-secondary);flex-shrink:0;}
.funnel-row .track{flex:1;height:22px;background:var(--surface-2);border:1px solid var(--border);
  border-radius:6px;overflow:hidden;}
.funnel-row .track > i{display:block;height:100%;background:var(--fill-accent);}
.funnel-row .n{width:120px;text-align:right;font-size:var(--fs-xs);flex-shrink:0;
  font-variant-numeric:tabular-nums;}
.admin-split{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-5);align-items:start;}
.spark{display:flex;align-items:flex-end;gap:6px;height:120px;}
.spark > div{flex:1;display:flex;flex-direction:column;align-items:center;gap:var(--space-1);min-width:0;}
.spark .b{width:100%;background:var(--fill-accent);border-radius:3px 3px 0 0;min-height:2px;}
.spark .d{font-size:11px;white-space:nowrap;color:var(--text-muted);}

/* --- 7. MOTION ----------------------------------------------------------
   Everything here is decoration-tolerant but state-first: entrances orient you
   in new content, the shimmer says "still working", the pop says "this is new".
   The reduced-motion block at the bottom of the file neutralises all of it —
   including the infinite ones, via animation-iteration-count:1.
   -------------------------------------------------------------------------- */
@keyframes rise{from{opacity:0;transform:translateY(10px);}to{opacity:1;transform:none;}}
@keyframes fade-in{from{opacity:0;}to{opacity:1;}}
@keyframes pop{0%{opacity:0;transform:scale(0.86);}60%{transform:scale(1.04);}100%{opacity:1;transform:scale(1);}}
@keyframes shimmer{from{background-position:-140% 0;}to{background-position:240% 0;}}
@keyframes halo{0%,100%{transform:scale(1);opacity:0.55;}50%{transform:scale(1.28);opacity:0;}}
@keyframes nudge{0%,100%{transform:none;}30%{transform:translateY(-3px);}60%{transform:translateY(-1px);}}

/* Cross-document page transitions. Chromium honours this; everywhere else it is
   an unknown at-rule and is skipped, so navigation just stays instant. */
@view-transition{navigation:auto;}

.anim-rise{animation:rise var(--dur) var(--ease) both;}
.anim-pop{animation:pop 260ms var(--ease) both;}

/* Landing hero, sequenced so the eye lands on the headline before the field. */
.card > .hero-title{animation:rise 420ms var(--ease) both;}
.card > .hero-sub{animation:rise 420ms var(--ease) 70ms both;}
.card > .form-inline{animation:rise 420ms var(--ease) 140ms both;}
.card > .inline-note{animation:rise 420ms var(--ease) 200ms both;}
.card > .link-row{animation:rise 420ms var(--ease) 240ms both;}
.card > .trust{animation:rise 420ms var(--ease) 300ms both;}

/* Result lists and tiles stagger in. Capped at 10 items: a 400-row following
   list must not spend 12s dealing itself onto the screen. */
.rows > .acct,.stat-grid > .stat,.metric-grid > .metric{animation:rise 320ms var(--ease) both;}
.rows > .acct:nth-child(n+11),.stat-grid > .stat:nth-child(n+11),
.metric-grid > .metric:nth-child(n+11){animation-delay:0ms;}
.rows > .acct:nth-child(1),.stat-grid > .stat:nth-child(1),.metric-grid > .metric:nth-child(1){animation-delay:0ms;}
.rows > .acct:nth-child(2),.stat-grid > .stat:nth-child(2),.metric-grid > .metric:nth-child(2){animation-delay:35ms;}
.rows > .acct:nth-child(3),.stat-grid > .stat:nth-child(3),.metric-grid > .metric:nth-child(3){animation-delay:70ms;}
.rows > .acct:nth-child(4),.stat-grid > .stat:nth-child(4),.metric-grid > .metric:nth-child(4){animation-delay:105ms;}
.rows > .acct:nth-child(5),.stat-grid > .stat:nth-child(5),.metric-grid > .metric:nth-child(5){animation-delay:140ms;}
.rows > .acct:nth-child(6),.stat-grid > .stat:nth-child(6),.metric-grid > .metric:nth-child(6){animation-delay:175ms;}
.rows > .acct:nth-child(7),.stat-grid > .stat:nth-child(7),.metric-grid > .metric:nth-child(7){animation-delay:210ms;}
.rows > .acct:nth-child(8),.stat-grid > .stat:nth-child(8),.metric-grid > .metric:nth-child(8){animation-delay:245ms;}
.rows > .acct:nth-child(9),.stat-grid > .stat:nth-child(9),.metric-grid > .metric:nth-child(9){animation-delay:280ms;}
.rows > .acct:nth-child(10),.stat-grid > .stat:nth-child(10),.metric-grid > .metric:nth-child(10){animation-delay:315ms;}

/* Row hover: lifts toward the pointer, and the external-link icon fades up. */
.acct{transition:transform var(--dur-fast) var(--ease),border-color var(--dur-fast) var(--ease),
  box-shadow var(--dur-fast) var(--ease);}
@media (hover:hover){
  .acct:hover{transform:translateY(-2px);border-color:var(--border-accent);
    box-shadow:0 6px 20px -12px rgba(0,0,0,0.45);}
  .acct .acct-link{opacity:0.5;transition:opacity var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease),background var(--dur-fast) var(--ease);}
  .acct:hover .acct-link{opacity:1;}
}

/* Dashboard filtering: one cheap fade on the container beats re-animating
   hundreds of rows. Re-triggered from JS by toggling the attribute. */
.rows[data-refiltered]{animation:fade-in 200ms var(--ease);}

.chip-btn{transition:background var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease),
  border-color var(--dur-fast) var(--ease),transform var(--dur-fast) var(--ease);}
.chip-btn:active{transform:scale(0.96);}
.chip.is-new{animation:pop 300ms var(--ease) both;}

/* Processing: the bar carries a travelling highlight so a stalled-looking
   percentage still reads as "running", and the spinner gets a breathing halo. */
.progress > .bar{position:relative;overflow:hidden;}
.progress > .bar::after{content:"";position:absolute;inset:0;
  background:linear-gradient(100deg,transparent 20%,rgba(255,255,255,0.45) 50%,transparent 80%);
  background-size:220% 100%;animation:shimmer 1.8s linear infinite;}
/* Meters show a level, not activity — no travelling highlight. */
.progress--static > .bar::after{display:none;}
/* A ring, not a filled disc: a same-coloured fill behind --bg-accent would be
   invisible, and z-index:-1 would drop it behind the card entirely. */
.disc{position:relative;}
.disc::before{content:"";position:absolute;inset:0;border-radius:50%;
  border:2px solid var(--border-accent);animation:halo 2.4s var(--ease) infinite;}

/* Paywall: skeletons shimmer rather than sit dead, and the unlock button
   catches light on hover. */
.skeleton-line,.blur .avatar{background:linear-gradient(100deg,var(--surface-1) 30%,
  var(--surface-2) 50%,var(--surface-1) 70%);background-size:220% 100%;
  animation:shimmer 2.2s linear infinite;}
.lock-panel .btn{position:relative;overflow:hidden;}
.lock-panel .btn::after{content:"";position:absolute;top:0;bottom:0;width:40%;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,0.28),transparent);
  transform:translateX(-180%);transition:transform 620ms var(--ease);}
.lock-panel .btn:hover::after{transform:translateX(320%);}
/* Three nudges, then still. An indefinitely bouncing element in the viewport is
   a distraction, not a cue. */
.lock-panel > .ti{display:inline-block;animation:nudge 2.8s var(--ease) 1.2s 3;}

/* Errors arrive rather than blink into place. */
.form-error[data-shown]{animation:rise 220ms var(--ease) both;}

/* In-button spinner for submit states, so the wait is legible on the control
   you just pressed. */
.btn .dots{display:inline-block;width:14px;height:14px;border-radius:50%;
  border:2px solid rgba(255,255,255,0.35);border-top-color:var(--on-accent);
  animation:spin 0.7s linear infinite;}

/* --- RESPONSIVE --------------------------------------------------------- */
@media (max-width:640px){
  .admin-split{grid-template-columns:1fr;}
}
@media (max-width:520px){
  .wrap{padding:var(--space-4) var(--space-3) var(--space-6);}
  .card{padding:var(--space-6) var(--space-4);}
  .trust{gap:var(--space-3);flex-direction:column;align-items:flex-start;text-align:left;}
  /* The topic label is the product's whole point — drop it to its own line
     on narrow screens rather than hiding it (the previous behaviour). */
  .acct{flex-wrap:wrap;}
  .acct-link{order:3;}
  .acct .cat{order:4;flex-basis:100%;background:none;padding:0;margin:2px 0 0 54px;
    font-size:12px;color:var(--text-muted);}
  .funnel-row .lbl{width:88px;}
  .funnel-row .n{width:84px;}
}

/* --- REDUCED MOTION ----------------------------------------------------- */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:0.01ms !important;animation-iteration-count:1 !important;
    transition-duration:0.01ms !important;scroll-behavior:auto !important;}
  /* The spinner is the only signal that a multi-minute job is alive, so keep it
     turning — just slowly enough not to trigger vestibular discomfort. */
  .spin{animation:spin 3s linear infinite !important;}
}
