/* ===================================================================
   MindSpring — shared base stylesheet
   Chrome used by every page: design tokens, reset, typography,
   buttons, nav (with mobile drawer), footer, and motion helpers.
   Page-specific styling lives inline in each page.
=================================================================== */

:root{
  --ink:#16241e;
  --ink-soft:#3c4c44;
  --paper:#ecEAE0;
  --paper-2:#e4e1d4;
  --card:#fbfaf4;
  --evergreen:#173629;
  --evergreen-2:#0f261c;
  --spring:#3e9c6c;
  --spring-deep:#2f7c54;
  --honey:#dda04c;
  --sage:#c7d1c1;
  --line:rgba(22,36,30,.12);
  --line-strong:rgba(22,36,30,.22);
  --line-dark:rgba(255,255,255,.14);
  --warn:#a5701f;
  --danger:#b23a2e;
  /* Correct / wrong answer surfaces. These exist because every game page used to
     hardcode the light pastels #e7f3ec / #fbeae7 with no dark override — which
     painted near-white text on a near-white wash in dark mode and made answer
     feedback invisible. Always use these, never the literals. */
  --ok-bg:#e7f3ec;
  --ok-fg:#2f7c54;
  --ok-bg-soft:#eef6f0;      /* the lighter hover tint of --ok-bg */
  --bad-bg:#fbeae7;
  --bad-fg:#b23a2e;
  /* Accent triples, kept for the few places that genuinely want a tinted ring
     (focus states, the notification dot). They are NOT a lighting system.

     These used to drive a neon bloom on buttons, the nav, the brand mark and a
     drifting backdrop behind the whole page. Swapping purple neon for green
     neon doesn't avoid the generic-AI look — the glow itself IS the tell, in
     any hue. Depth now comes from real, physical shadow: a soft ambient layer
     plus a tighter contact layer, the way an object actually sits on a page. */
  --glow-a:70,214,132;
  --glow-b:255,181,74;
  --shadow-sm:0 1px 2px rgba(15,38,28,.06),0 1px 1px rgba(15,38,28,.04);
  --shadow-md:0 2px 4px rgba(15,38,28,.06),0 12px 24px -12px rgba(15,38,28,.34);
  --shadow-lg:0 4px 8px rgba(15,38,28,.07),0 28px 56px -28px rgba(15,38,28,.45);
  --r-lg:22px;
  --r-md:14px;
  --r-sm:9px;
  --maxw:1180px;
}

/* ---------- Dark theme ----------
   Applied by setting data-theme="dark" on <html> (a tiny inline head script
   on every page reads the saved preference before first paint, so there's no
   flash). Only the design tokens flip; the whole site is built on these vars,
   so components follow automatically. A few chrome pieces that hard-code a
   light value (nav glass, primary button) get explicit dark overrides below. */
html[data-theme="dark"]{
  --ink:#e7ede9;
  --ink-soft:#9fb1a7;
  --paper:#0e1712;
  --paper-2:#132019;
  --card:#17241d;
  --evergreen:#173629;
  --evergreen-2:#0c1d15;
  --spring:#4fb27e;
  --spring-deep:#6fc79a;
  --honey:#e0a95a;
  --sage:#26362d;
  --line:rgba(255,255,255,.10);
  --line-strong:rgba(255,255,255,.20);
  --warn:#d99a2b;
  --danger:#ec7a5f;
  /* Translucent washes, not pastels — they tint the dark card underneath rather
     than punching a light hole in it, so the foreground stays legible. */
  --ok-bg:rgba(79,178,126,.18);
  --ok-fg:#7fdcaa;
  --ok-bg-soft:rgba(79,178,126,.09);
  --bad-bg:rgba(236,122,95,.18);
  --bad-fg:#f0937c;
  --glow-a:96,255,160;
  --glow-b:255,201,110;
  /* On a near-black canvas a drop shadow barely reads, so depth comes mostly
     from a 1px top highlight — the edge catching light — over a deep shadow.
     That's how a raised surface actually looks in the dark; a colored halo
     around the element is not. */
  --shadow-sm:0 1px 2px rgba(0,0,0,.45),inset 0 1px 0 rgba(255,255,255,.04);
  --shadow-md:0 2px 4px rgba(0,0,0,.4),0 12px 24px -12px rgba(0,0,0,.7),inset 0 1px 0 rgba(255,255,255,.05);
  --shadow-lg:0 4px 10px rgba(0,0,0,.45),0 28px 56px -28px rgba(0,0,0,.8),inset 0 1px 0 rgba(255,255,255,.06);
}
/* Primary button: in dark, fill with the bright spring green and use the deep
   evergreen for the label so it stays vivid and high-contrast on a dark page. */
html[data-theme="dark"] .btn-primary{background:var(--spring);color:var(--evergreen-2);}
html[data-theme="dark"] .btn-primary:hover{background:var(--spring-deep);}
/* Nav glass tint tracks the dark paper instead of the cream one. */
html[data-theme="dark"] .nav{background:rgba(14,23,18,.82);}
html[data-theme="dark"] .nav.scrolled{background:rgba(14,23,18,.94);}

*{box-sizing:border-box;}
/* The `hidden` attribute must always win. Component rules like `.btn{display:...}`
   are author styles that override the UA `[hidden]{display:none}`, which would
   otherwise leak hidden elements (e.g. the admin-only button) into view. */
[hidden]{display:none !important;}
html{scroll-behavior:smooth;}
body{
  margin:0;
  background:var(--paper);
  color:var(--ink);
  font-family:"Inter",system-ui,sans-serif;
  font-size:17px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}
/* A single, still, barely-there warm wash from the top of the page — enough to
   keep the canvas from reading as flat grey, and nothing more.

   What used to be here: four saturated spring/honey blobs, blurred, drifting on
   a 22s loop, giving every page a "glowing from behind" feel. That effect is
   the clearest signal of a generated page, and it isn't rescued by being green
   instead of purple. Paper doesn't glow. The brand now lives in the ink, the
   accents and the type, where someone can actually read it. */
body::before{
  content:"";
  position:fixed;
  inset:0;
  z-index:-1;
  pointer-events:none;
  background:linear-gradient(180deg, rgba(23,54,41,.05), transparent 34%);
}
html[data-theme="dark"] body::before{
  background:linear-gradient(180deg, rgba(96,255,160,.035), transparent 30%);
}
h1,h2,h3,h4{
  font-family:"Bricolage Grotesque","Inter",sans-serif;
  font-weight:700;
  line-height:1.1;
  letter-spacing:-.015em;
  margin:0;
}
p{margin:0;}
a{color:inherit;text-decoration:none;}
img{max-width:100%;display:block;}
::selection{background:var(--honey);color:var(--evergreen-2);}
:focus-visible{outline:2px solid var(--spring);outline-offset:2px;border-radius:4px;}

.wrap{width:100%;max-width:var(--maxw);margin:0 auto;padding:0 24px;}
.mono{font-family:"IBM Plex Mono",monospace;}

.eyebrow{
  font-family:"IBM Plex Mono",monospace;
  font-size:12.5px;font-weight:500;letter-spacing:.16em;text-transform:uppercase;
  color:var(--spring-deep);display:inline-flex;align-items:center;gap:9px;
}
.eyebrow::before{content:"";width:22px;height:1px;background:var(--spring-deep);opacity:.6;}

/* ---------- Buttons ---------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  font-family:"Inter",sans-serif;font-weight:600;font-size:15px;
  padding:13px 22px;border-radius:100px;border:1px solid transparent;
  cursor:pointer;transition:transform .18s cubic-bezier(.34,1.56,.64,1),background .18s ease,border-color .18s ease,box-shadow .18s ease;
  white-space:nowrap;
}
.btn svg{width:17px;height:17px;transition:transform .18s ease;}
.btn:hover svg{transform:translateX(2px);}
/* A quick squish on press — the bounce-back on release comes free from the
   button's own cubic-bezier transition above. */
.btn:active{transform:scale(.94);}
/* Pill buttons get a ring that follows their shape, rather than the global
   square outline. A crisp two-tone ring — not a bloom — so it stays legible
   against both the cream and the dark canvas. */
.btn:focus-visible{outline:none;box-shadow:0 0 0 2px var(--paper),0 0 0 4px var(--spring-deep);}
/* The primary button used to glow AND pulse on a 3.6s loop, forever, on every
   page. A button that breathes at you is not more inviting — it's restless, and
   it's the second-clearest generated-page tell after the glowing backdrop.
   It now just sits there looking like a good button, and moves when touched. */
.btn-primary{
  background:var(--evergreen);color:#f4f2e8;
  box-shadow:var(--shadow-sm);
}
.btn-primary:hover{background:var(--evergreen-2);transform:translateY(-1px);box-shadow:var(--shadow-md);}
.btn-primary:active{transform:translateY(0) scale(.98);box-shadow:var(--shadow-sm);}
.btn-ghost{background:transparent;color:var(--ink);border-color:var(--line-strong);}
.btn-ghost:hover{border-color:var(--ink);background:var(--card-2);transform:translateY(-1px);}
.btn-light{background:#f4f2e8;color:var(--evergreen);}
.btn-light:hover{background:#fff;transform:translateY(-1px);box-shadow:var(--shadow-md);}
.btn-block{width:100%;}

/* ---------- Nav ---------- */
/* Flat and quiet at rest — just a hairline. The shadow appears only once the
   page has scrolled under it, which is the one moment it's actually telling
   you something (there's content above). */
.nav{position:sticky;top:0;z-index:60;background:rgba(236,234,224,.86);backdrop-filter:blur(10px);border-bottom:1px solid var(--line);transition:box-shadow .25s ease,background .25s ease,border-color .25s ease;}
.nav.scrolled{background:rgba(236,234,224,.96);box-shadow:0 1px 3px rgba(15,38,28,.08),0 8px 24px -16px rgba(15,38,28,.35);}
.nav-inner{display:flex;align-items:center;justify-content:space-between;height:70px;}
.brand{display:flex;align-items:center;gap:11px;font-family:"Bricolage Grotesque",sans-serif;font-weight:700;font-size:20px;letter-spacing:-.02em;color:var(--ink);}
.brand .mark{position:relative;width:34px;height:34px;border-radius:10px;background:var(--evergreen);display:grid;place-items:center;box-shadow:var(--shadow-sm);transition:transform .32s cubic-bezier(.34,1.56,.64,1);}
.brand:hover .mark{transform:rotate(-6deg);}
.brand .mark svg{width:20px;height:20px;position:relative;z-index:1;}
.nav-links{display:flex;align-items:center;gap:34px;}
.nav-links a{font-size:15px;color:var(--ink-soft);font-weight:500;transition:color .15s ease;position:relative;}
.nav-links a::after{content:"";position:absolute;left:0;right:0;bottom:-6px;height:2px;background:var(--spring);border-radius:2px;transform:scaleX(0);transform-origin:left center;transition:transform .24s cubic-bezier(.22,.61,.36,1);}
.nav-links a:hover{color:var(--ink);}
.nav-links a:hover::after{transform:scaleX(1);}
.nav-links a.active{color:var(--ink);}
.nav-links a.active::after{transform:scaleX(1);}
.nav-cta{display:flex;align-items:center;gap:14px;}
.nav-toggle{display:none;background:none;border:1px solid var(--line-strong);border-radius:9px;width:42px;height:42px;place-items:center;cursor:pointer;color:var(--ink);}
.nav-toggle svg{width:20px;height:20px;}

/* Hover dropdowns in the desktop nav ("My Resources" -> Notes/Flashcards,
   "Tutor" -> Sage/Explain PDF). Reuses .nav-menu-pop's visual language. Mouse
   hover AND keyboard focus-within both reveal the panel; below the 940px
   breakpoint .nav-links is already display:none (replaced by .nav-drawer,
   which lists the same destinations as plain links), so no touch/mobile
   handling is needed here. */
.nav-drop{position:relative;}
.nav-drop-label{display:inline-flex;align-items:center;gap:5px;background:none;border:none;padding:0;margin:0;font:inherit;font-size:15px;color:var(--ink-soft);font-weight:500;cursor:pointer;transition:color .15s ease;}
.nav-drop-label:hover,.nav-drop:hover .nav-drop-label,.nav-drop:focus-within .nav-drop-label,.nav-drop.open .nav-drop-label{color:var(--ink);}
.nav-drop-label svg{width:13px;height:13px;opacity:.7;transition:transform .18s ease;}
.nav-drop:hover .nav-drop-label svg,.nav-drop:focus-within .nav-drop-label svg,.nav-drop.open .nav-drop-label svg{transform:rotate(180deg);}
.nav-drop:has(.nav-drop-item.active) .nav-drop-label{color:var(--ink);}
.nav-drop-pop{position:absolute;top:calc(100% + 14px);left:50%;transform:translateX(-50%) translateY(-6px);min-width:172px;background:var(--card);border:1px solid var(--line);border-radius:var(--r-md);box-shadow:var(--shadow-lg);padding:7px;opacity:0;pointer-events:none;transition:opacity .16s ease,transform .16s ease;z-index:80;}
/* Invisible bridge over the gap so the pointer can travel from label to panel
   without the hover state closing between them. */
.nav-drop-pop::before{content:"";position:absolute;left:0;right:0;top:-14px;height:14px;}
/* .open is the click/tap toggle app.js adds — touch input doesn't reliably
   trigger :hover, so without it these dropdowns were only reachable by mouse. */
.nav-drop:hover .nav-drop-pop,.nav-drop:focus-within .nav-drop-pop,.nav-drop.open .nav-drop-pop{opacity:1;transform:translateX(-50%) translateY(0);pointer-events:auto;}
.nav-drop-item{display:block;padding:9px 12px;border-radius:9px;font-size:14px;font-weight:500;color:var(--ink);white-space:nowrap;transition:background .13s ease;}
.nav-drop-item:hover{background:var(--paper);}
.nav-drop-item.active{color:var(--spring-deep);}
@media(prefers-reduced-motion:reduce){.nav-drop-pop,.nav-drop-label svg{transition:none;}}

/* signed-in account menu (desktop) — a name chip that drops a small popover */
.nav-menu{position:relative;}
.nav-menu-btn{display:inline-flex;align-items:center;gap:9px;background:var(--card);border:1px solid var(--line-strong);border-radius:100px;padding:6px 12px 6px 6px;cursor:pointer;color:var(--ink);font-family:inherit;font-size:14px;font-weight:600;transition:border-color .15s ease,box-shadow .15s ease,transform .2s cubic-bezier(.34,1.56,.64,1);}
.nav-menu-btn:hover{border-color:var(--ink);background:var(--card-2);}
.nav-menu-btn .nav-ava{width:28px;height:28px;border-radius:50%;background:var(--evergreen);color:#f4f2e8;display:grid;place-items:center;font-size:13px;font-weight:700;flex:none;}
html[data-theme="dark"] .nav-menu-btn .nav-ava{background:var(--spring);color:var(--evergreen-2);}
.nav-menu-btn .nav-chev{width:15px;height:15px;transition:transform .2s ease;opacity:.6;}
.nav-menu[data-open="1"] .nav-menu-btn .nav-chev{transform:rotate(180deg);}
.nav-menu-pop{position:absolute;top:calc(100% + 10px);right:0;min-width:210px;background:var(--card);border:1px solid var(--line);border-radius:var(--r-md);box-shadow:var(--shadow-lg);padding:7px;opacity:0;transform:translateY(-6px) scale(.98);transform-origin:top right;pointer-events:none;transition:opacity .16s ease,transform .16s ease;z-index:80;}
.nav-menu[data-open="1"] .nav-menu-pop{opacity:1;transform:none;pointer-events:auto;}
.nav-menu-head{padding:9px 11px 10px;border-bottom:1px solid var(--line);margin-bottom:6px;}
.nav-menu-head .nm-name{font-weight:700;font-size:14px;color:var(--ink);}
.nav-menu-head .nm-mail{font-size:12px;color:var(--ink-soft);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:180px;}
.nav-menu-item{display:flex;align-items:center;gap:10px;width:100%;text-align:left;background:none;border:0;border-radius:9px;padding:10px 11px;font-family:inherit;font-size:14px;font-weight:500;color:var(--ink);cursor:pointer;transition:background .13s ease;}
.nav-menu-item:hover{background:var(--paper);}
.nav-menu-item svg{width:16px;height:16px;opacity:.7;flex:none;}
.nav-menu-item.is-out{color:var(--danger);}
.nav-menu-sep{height:1px;background:var(--line);margin:6px 4px;}

/* notifications bell (injected by notifications.js, sibling of .nav-cta) */
.nav-notif{position:relative;display:flex;align-items:center;}
.nn-btn{position:relative;width:40px;height:40px;display:grid;place-items:center;border:1px solid var(--line-strong);background:var(--card);border-radius:50%;cursor:pointer;color:var(--ink);transition:border-color .15s ease,background .15s ease;}
.nn-btn:hover{border-color:var(--ink);}
.nn-btn svg{width:19px;height:19px;}
.nn-btn.has-unread{border-color:var(--spring);}
.nn-badge{position:absolute;top:-3px;right:-3px;min-width:18px;height:18px;padding:0 4px;border-radius:100px;background:var(--honey);color:var(--evergreen);font-family:"IBM Plex Mono",monospace;font-size:11.5px;font-weight:700;line-height:1;display:grid;place-items:center;border:2px solid var(--paper);}
/* Unread state reads from the honey count badge above; the bell itself just
   firms up its border rather than lighting up. */
.nn-btn.has-unread{border-color:var(--ink);}
html[data-theme="dark"] .nn-badge{border-color:var(--paper);}
.nn-pop{position:absolute;top:calc(100% + 10px);right:0;width:340px;max-width:calc(100vw - 32px);background:var(--card);border:1px solid var(--line);border-radius:var(--r-md);box-shadow:var(--shadow-lg);z-index:80;overflow:hidden;animation:nnPop .16s ease;}
@keyframes nnPop{from{opacity:0;transform:translateY(-6px) scale(.98);}to{opacity:1;transform:none;}}
.nn-head{display:flex;align-items:center;justify-content:space-between;padding:13px 15px;border-bottom:1px solid var(--line);font-family:"Bricolage Grotesque",sans-serif;font-weight:700;font-size:15px;color:var(--ink);}
.nn-list{max-height:min(420px,60vh);overflow-y:auto;}
.nn-empty{padding:26px 18px 28px;text-align:center;color:var(--ink-soft);font-size:13.5px;line-height:1.5;}
/* Faceted bell — matches the two-tone empty-state illustrations used across
   the site, added via CSS so notifications.js needs no markup change. */
.nn-empty::before{
  content:"";display:block;width:44px;height:44px;margin:0 auto 12px;
  background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><path fill="%23e3e6dc" d="M24 8c-7 0-11 5-11 12v8l-4 6h30l-4-6v-8c0-7-4-12-11-12z"/><path fill="%23c9cfc3" d="M24 8c-1.2 0-2.3.15-3.4.44C25.6 10 28 14.4 28 20v8l3.6 6H39l-4-6v-8c0-7-4-12-11-12z"/><path fill="%23c9cfc3" d="M20 36a4 4 0 0 0 8 0z"/></svg>') center/contain no-repeat;
}
.nn-item{display:flex;gap:11px;padding:13px 15px;border-bottom:1px solid var(--line);}
.nn-item:last-child{border-bottom:0;}
.nn-item.is-unread{background:rgba(62,156,108,.07);}
.nn-dot{flex:none;width:9px;height:9px;border-radius:50%;margin-top:5px;background:var(--sage);}
.nn-item.is-unread .nn-dot{background:var(--spring);}
.nn-item.t-referral .nn-dot,.nn-item.t-credits .nn-dot,.nn-item.t-promo .nn-dot{background:var(--honey);}
.nn-main{min-width:0;flex:1;}
.nn-title{font-weight:600;font-size:14px;color:var(--ink);line-height:1.3;}
.nn-body{margin-top:3px;font-size:13px;color:var(--ink-soft);line-height:1.45;}
.nn-when{margin-top:5px;font-family:"IBM Plex Mono",monospace;font-size:12px;letter-spacing:.03em;color:var(--ink-soft);opacity:.85;}

/* mobile drawer */
.nav-drawer{
  display:none;position:fixed;inset:0 0 0 auto;z-index:70;width:min(340px,86vw);
  background:var(--card);border-left:1px solid var(--line);box-shadow:var(--shadow-lg);
  padding:22px;transform:translateX(100%);transition:transform .28s cubic-bezier(.4,0,.2,1);
  flex-direction:column;gap:6px;
  /* The link list + injected profile/settings/logout can outgrow the
     viewport on short phones — without this, anything past the fold
     (Profile included) was simply unreachable, not just unscrolled-to. */
  overflow-y:auto;
}
.nav-scrim{display:none;position:fixed;inset:0;z-index:65;background:rgba(15,38,28,.34);opacity:0;transition:opacity .28s ease;}
.nav-drawer-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;}
.nav-drawer a.d-link{display:block;padding:13px 12px;border-radius:10px;font-size:16px;font-weight:500;color:var(--ink);transition:background .15s ease;}
.nav-drawer a.d-link:hover{background:var(--paper);}
.nav-drawer .d-divider{height:1px;background:var(--line);margin:12px 0;}
.nav-drawer .btn{margin-top:6px;}
body.menu-open{overflow:hidden;}
body.menu-open .nav-drawer{display:flex;transform:translateX(0);}
body.menu-open .nav-scrim{display:block;opacity:1;}

/* ---------- Footer ---------- */
.site-footer{padding:64px 0 40px;border-top:1px solid var(--line);}
.foot-grid{display:flex;justify-content:space-between;gap:40px;flex-wrap:wrap;}
.foot-brand{max-width:300px;}
.foot-brand p{margin-top:14px;font-size:14px;color:var(--ink-soft);line-height:1.6;}
.foot-cols{display:flex;gap:64px;flex-wrap:wrap;}
.foot-col h5{font-family:"IBM Plex Mono",monospace;font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-soft);margin:0 0 14px;font-weight:600;}
.foot-col a{display:block;font-size:15px;color:var(--ink-soft);margin-bottom:10px;transition:color .15s ease;}
.foot-col a:hover{color:var(--ink);}
.foot-bottom{margin-top:48px;padding-top:22px;border-top:1px solid var(--line);display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap;font-size:13px;color:var(--ink-soft);}
.foot-bottom .mono{font-size:12px;}

/* ---------- Motion helpers ---------- */
.reveal{opacity:0;transform:translateY(18px);}
.reveal.in{opacity:1;transform:none;transition:opacity .6s cubic-bezier(.22,.61,.36,1),transform .6s cubic-bezier(.22,.61,.36,1);}
.reveal.d1{transition-delay:.07s;}
.reveal.d2{transition-delay:.14s;}
.reveal.d3{transition-delay:.21s;}

/* ---------- Page-load entrance (above-the-fold hero) ----------
   Pure-CSS so it fires even before app.js runs — no flash of hidden
   content if the script is slow. `--seq` sets each element's place in
   the stagger; the deck gets its own softer scale-in. */
/* A touch of overshoot (the "back out" cubic-bezier below 0 then past 1) so
   elements pop into place rather than just fading up — reads as playful
   without being cartoonish, and is a single shared timing swap site-wide. */
@keyframes ms-rise{from{opacity:0;transform:translateY(20px) scale(.97);}to{opacity:1;transform:none;}}
@keyframes ms-deck-in{from{opacity:0;transform:translateY(30px) scale(.96) rotate(-.6deg);}to{opacity:1;transform:none;}}
.load-rise{opacity:0;animation:ms-rise .62s cubic-bezier(.2,1.1,.4,1) both;animation-delay:calc(var(--seq,0) * 90ms + 80ms);}
.load-deck{opacity:0;animation:ms-deck-in .78s cubic-bezier(.2,1.1,.4,1) both;animation-delay:.24s;}

/* ---------- Branded loader + tag badges ---------- */
/* A trio of bouncing dots (one div, two pseudo-elements — no extra markup)
   for boot / "loading your …" states, plus a row that pairs it with a label.
   Bouncier and more playful than a spinner ring; still just brand tokens. */
@keyframes ms-dot-bounce{
  0%,60%,100%{transform:translateY(0) scale(.78);opacity:.55;}
  30%{transform:translateY(-8px) scale(1.15);opacity:1;}
}
.ms-loader{
  position:relative;display:inline-block;vertical-align:middle;
  width:8px;height:8px;border-radius:50%;margin:0 15px;
  background:var(--honey);
  animation:ms-dot-bounce .85s ease-in-out infinite;animation-delay:.12s;
}
.ms-loader::before,.ms-loader::after{
  content:"";position:absolute;top:0;width:8px;height:8px;border-radius:50%;
  animation:ms-dot-bounce .85s ease-in-out infinite;
}
.ms-loader::before{left:-15px;background:var(--spring);animation-delay:0s;}
.ms-loader::after{right:-15px;background:var(--spring-deep);animation-delay:.24s;}
.ms-loading-row{display:inline-flex;align-items:center;gap:10px;color:var(--ink-soft);font-size:15px;}

/* Earned/derived profile tag (OWNER, SUPPORTER). Mono uppercase pill in the
   same family as .p-badge / .promo-badge — distinct, non-purple accents. */
.tag-badge{
  display:inline-flex;align-items:center;gap:5px;
  font-family:"IBM Plex Mono",monospace;font-size:11.5px;font-weight:600;
  letter-spacing:.12em;text-transform:uppercase;
  padding:3px 9px;border-radius:100px;line-height:1;vertical-align:middle;
  border:1px solid transparent;
}
.tag-badge[data-tag="OWNER"]{background:var(--evergreen);color:var(--honey);border-color:var(--evergreen);}
.tag-badge[data-tag="SUPPORTER"]{background:var(--sage);color:var(--evergreen);border-color:var(--line-strong);}
html[data-theme="dark"] .tag-badge[data-tag="SUPPORTER"]{color:var(--spring-deep);}

/* ---------- Shared responsive (chrome) ---------- */
/* Guest pages carry up to seven nav links (four features + three marketing).
   Between the 940px collapse and the 1180px container they need tighter spacing
   or they overflow the bar. Signed-in users see only the four feature links. */
@media(max-width:1180px){
  .nav-links{gap:20px;}
  .nav-links a{font-size:14px;}
}
@media(max-width:940px){
  .nav-links,.nav-cta{display:none;}
  /* keep the bell pinned to the right, just left of the menu button */
  .nav-notif{margin-left:auto;margin-right:10px;}
  .nav-toggle{display:grid;}
}
@media(max-width:560px){
  body{font-size:16px;}
  .wrap{padding:0 18px;}
  .nav-inner{height:64px;}
  .foot-cols{gap:36px;}
}
@media(prefers-reduced-motion:reduce){
  *{transition:none!important;animation:none!important;scroll-behavior:auto;}
  /* animations are off — make sure nothing is left invisible */
  .reveal,.load-rise,.load-deck{opacity:1!important;transform:none!important;}
  /* the bounce is decorative motion, not the functional signal — the loading
     label text already says so, so just freeze the three dots at full opacity
     instead of forcing the bounce to keep running. */
  .ms-loader,.ms-loader::before,.ms-loader::after{opacity:1!important;transform:none!important;}
}
