/* style.css — concatenation of tokens + base + layout + components + pages + motion.
   Edit the sources in /css/ and re-concatenate in the same order. Pages load only this file. */

/* tokens.css — the ONLY file allowed to contain hex codes */
:root{
  /* Signature brand gradient: deep teal/cyan -> electric royal blue -> vibrant violet. */
  --brand-gradient:linear-gradient(135deg,#008ba3 0%,#1e5cd9 50%,#8c25e2 100%);
  --brand-gradient-hover:linear-gradient(135deg,#007a91 0%,#184ec0 50%,#7b1ed0 100%);
  --primary-blue:#1e5cd9;
  --primary-purple:#8c25e2;
  --primary-teal:#008ba3;

  --brand:#1E5CD9; --brand-lt:#4A7EE8; --brand-dk:#184EC0;
  --accent:#008BA3; --coral:#FF6B57; --amber:#F5A524;
  --bg:#FBFAFF; --surface:#FFFFFF; --surface-2:#F1F4FC;
  --text:#151A2B; --muted:#565E7A; --line:#E1E6F2;
  --header-bg:#14204A; --header-fg:#FFFFFF;
  --ok:#0E9488; --danger:#F43F5E;
  /* Legacy aliases — both now resolve to the signature gradient. */
  --grad-brand:var(--brand-gradient);
  --grad-cta:var(--brand-gradient);
  --r-sm:8px; --r-md:14px; --r-lg:20px; --r-pill:999px;
  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:24px; --sp-6:32px; --sp-7:48px;
  --sh-1:0 1px 2px rgba(21,26,43,.06);
  --sh-2:0 4px 14px rgba(30,92,217,.10);
  --sh-3:0 12px 34px rgba(30,92,217,.18);
  --ring:0 0 0 3px rgba(30,92,217,.20);
  --text-on-grad:0 1px 2px rgba(0,0,0,.28);
  --ff-head:'Times New Roman',Times,serif;
  --ff-body:'Times New Roman',Times,serif;
  --ff-mono:ui-monospace,'SFMono-Regular',Menlo,Consolas,monospace;
  /* Generated Unicode output only. Never overridden by the serif rule: Times New Roman
     has no glyphs for the stylish alphabets, so output would render as boxes. */
  --ff-glyph:'Segoe UI Symbol','Noto Sans Symbols 2','Apple Color Emoji','Noto Color Emoji',sans-serif;
  --dur:220ms; --ease:cubic-bezier(.22,.61,.36,1);
  --shell:760px; --shell-wide:1120px;
}
html[data-theme="dark"]{
  --bg:#0A0D1A; --surface:#131832; --surface-2:#1C2242; --text:#E8EBF6;
  --muted:#9BA4C4; --line:#252B4C; --brand:#6D96F5; --accent:#22C3D6;
  --header-bg:#0E1329; --sh-1:0 1px 2px rgba(0,0,0,.5);
  --sh-2:0 4px 14px rgba(0,0,0,.4); --sh-3:0 12px 34px rgba(0,0,0,.55);
  --ring:0 0 0 3px rgba(109,150,245,.28);
}

/* base.css — reset, typography, article */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}
*,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important}}
/* ---------------------------------------------------------------- global typography
   Times New Roman across the whole interface. The :not() list is deliberate: those
   surfaces render generated Unicode output (stylish alphabets, symbols, emoji), and
   Times New Roman has no glyphs for them — forcing it there would show boxes instead of
   the product. They keep --ff-glyph. */
body,h1,h2,h3,h4,h5,h6,p,span,a,li,label,small,strong,em,summary,
input,button,select,textarea,
.btn,.chip,.tag,.count,.field>label,.drawer__label,.ftr__h{
  font-family:'Times New Roman',Times,serif;
}
.bio-block,.result__text,.biocard__text,.nickcard__name,.ig__bio,.ig__av span,
.fontrow__t,.symgrid button,.chips .chip>span[aria-hidden],.drawer__list .ic,
.ftr__list .ic,.catcard .ic,.toolcard .ic,.ig__hl div span{
  font-family:var(--ff-glyph)!important;
}

body{margin:0;background:var(--bg);color:var(--text);font-family:var(--ff-body);
  font-size:16.5px;line-height:1.62;font-weight:400;overflow-x:hidden;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
@media(min-width:820px){body{font-size:17.5px;line-height:1.68}}
img,svg,video{max-width:100%;height:auto;display:block}
h1,h2,h3,h4{font-family:var(--ff-head);line-height:1.18;margin:0 0 var(--sp-3);
  text-wrap:balance;letter-spacing:0}
h1{font-size:29px;font-weight:700;letter-spacing:-.005em}
h2{font-size:23px;font-weight:700}
h3{font-size:18.5px;font-weight:700}
@media(min-width:600px){h1{font-size:35px}}
@media(min-width:820px){h1{font-size:43px;line-height:1.12}h2{font-size:29px}h3{font-size:21px}}
@media(min-width:1120px){h1{font-size:47px}}
p{margin:0 0 var(--sp-4);text-wrap:pretty}
a{color:var(--brand);text-decoration:none}
a:hover{color:var(--brand-lt);text-decoration:underline}
small,.meta{font-size:13.5px;font-weight:400;color:var(--muted)}
@media(min-width:820px){small,.meta{font-size:14px}}
ul,ol{margin:0 0 var(--sp-4);padding-left:1.25em}
li{margin-bottom:var(--sp-2)}
hr{border:0;border-top:1px solid var(--line);margin:var(--sp-6) 0}
code,kbd{font-family:var(--ff-mono);font-size:.9em;background:var(--surface-2);
  padding:2px 6px;border-radius:var(--r-sm)}
:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
/* Author display rules (.field, .btn) outrank the UA [hidden] rule, so hidden needs
   restating here or the attribute silently does nothing. */
[hidden]{display:none!important}
.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}
.shell{width:100%;max-width:var(--shell);margin:0 auto;padding:var(--sp-2) var(--sp-4) var(--sp-4)}
.shell--wide{max-width:var(--shell-wide)}
.stack>*+*{margin-top:var(--sp-5)}
@media(min-width:820px){.stack>*+*{margin-top:var(--sp-6)}}
/* The article is the last thing on most pages; it must not push the footer away. */
.stack>.seo:last-child{margin-bottom:0}

/* article */
.seo{min-height:320px}
.seo h2{margin-top:var(--sp-5)}
.seo h3{margin-top:var(--sp-4)}
.seo>*:first-child{margin-top:0}
.seo>*:last-child{margin-bottom:0}
.seo ul li::marker{color:var(--brand)}
.seo .lead{font-size:1.06em;color:var(--muted)}
.seo blockquote{margin:0 0 var(--sp-4);padding:var(--sp-4);background:var(--surface-2);
  border-radius:var(--r-md);font-style:normal}
.bio-block{font-family:var(--ff-glyph);white-space:pre-line;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--r-md);padding:var(--sp-4);
  margin:0 0 var(--sp-3);font-size:16px;line-height:1.9;box-shadow:var(--sh-1)}
.linkrow{display:flex;flex-wrap:wrap;gap:var(--sp-2) var(--sp-3);padding:0;list-style:none}
.linkrow li{margin:0}
.js noscript{display:none}
noscript .nojs{display:block;padding:var(--sp-4);background:var(--surface-2);
  border-radius:var(--r-md);margin-bottom:var(--sp-5)}

/* layout.css — header, drawer, footer, reserves */
[data-layout="header"]{min-height:56px;position:relative;z-index:40}
@media(min-width:820px){[data-layout="header"]{min-height:64px}}
[data-layout="header"]::before{content:"";position:fixed;inset:0 0 auto 0;height:56px;
  background:var(--header-bg);z-index:1}
@media(min-width:820px){[data-layout="header"]::before{height:64px}}
[data-layout="header"]:has(.hdr)::before{display:none}
[data-layout="footer"]{min-height:0}
[data-ad-slot]{min-height:0;display:block}
[data-ad-slot].is-live{min-height:100px;margin:var(--sp-5) 0}

.hdr{position:sticky;top:0;z-index:40;background:var(--header-bg);color:var(--header-fg);
  border-bottom:1px solid rgba(255,255,255,.08)}
.hdr__in{max-width:var(--shell-wide);margin:0 auto;height:56px;padding:0 var(--sp-3);
  display:flex;align-items:center;gap:var(--sp-3)}
@media(min-width:820px){.hdr__in{height:64px;padding:0 var(--sp-5)}}
.brand{display:flex;align-items:center;gap:var(--sp-2);color:var(--header-fg);
  font-family:var(--ff-head);font-weight:700;font-size:16px;letter-spacing:-.01em;margin-right:auto}
.brand:hover{text-decoration:none;color:var(--header-fg)}
.brand__tile{width:32px;height:32px;border-radius:9px;display:block;flex:none;
  box-shadow:var(--sh-1);overflow:hidden}
.brand__tile img,.brand__tile svg{width:100%;height:100%;display:block;border-radius:9px}
.hdr__nav{display:none;gap:var(--sp-4);margin-right:var(--sp-4)}
@media(min-width:980px){.hdr__nav{display:flex}}
.hdr__nav a{color:rgba(255,255,255,.86);font-size:14px;font-weight:500}
.hdr__nav a:hover{color:#fff;text-decoration:none}
.hdr__nav a[aria-current="page"]{color:#fff;box-shadow:inset 0 -2px 0 var(--primary-purple)}
.iconbtn{width:44px;height:44px;flex:none;display:grid;place-items:center;border:0;
  background:transparent;color:var(--header-fg);border-radius:var(--r-pill);cursor:pointer;
  font-size:18px;line-height:1;transition:background var(--dur) var(--ease)}
.iconbtn:hover{background:rgba(255,255,255,.12)}
.iconbtn:active{transform:scale(.94)}
.iconbtn svg{width:22px;height:22px;fill:none;stroke:currentColor;stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round}

.backdrop{position:fixed;inset:0;background:rgba(11,13,24,.6);opacity:0;visibility:hidden;
  z-index:60;transition:opacity var(--dur) var(--ease),visibility var(--dur)}
.backdrop.is-open{opacity:1;visibility:visible}
.drawer{position:fixed;top:0;left:0;bottom:0;width:82vw;max-width:320px;z-index:70;
  background:var(--surface);border-right:1px solid var(--line);
  transform:translateX(-100%);transition:transform 260ms var(--ease);
  display:flex;flex-direction:column;overscroll-behavior:contain}
.drawer.is-open{transform:translateX(0)}
@media(prefers-reduced-motion:reduce){.drawer{transition:none}}
.drawer__head{background:var(--brand-gradient);color:#fff;padding:var(--sp-4);
  display:flex;align-items:center;gap:var(--sp-2)}
.drawer__head .brand{color:#fff;font-size:16px;text-shadow:var(--text-on-grad)}
.drawer__body{flex:1;overflow-y:auto;padding:var(--sp-3) var(--sp-3) var(--sp-6);-webkit-overflow-scrolling:touch}
.drawer__search{display:flex;align-items:center;gap:var(--sp-2);margin:0 0 var(--sp-2);
  background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-pill);padding:0 var(--sp-3)}
.drawer__search input{flex:1;height:42px;border:0;background:transparent;color:var(--text);
  font:inherit;font-size:14px;outline:none}
.drawer__group{margin-top:var(--sp-4)}
.drawer__label{font-size:11.5px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;
  color:var(--muted);padding:0 var(--sp-2);margin-bottom:var(--sp-2)}
.drawer__list{list-style:none;margin:0;padding:0}
.drawer__list li{margin:0}
.drawer__list a{display:flex;align-items:center;gap:var(--sp-3);min-height:44px;
  padding:var(--sp-2) var(--sp-2);border-radius:var(--r-sm);color:var(--text);font-size:14.5px}
.drawer__list a:hover{background:var(--surface-2);text-decoration:none}
.drawer__list a[aria-current="page"]{background:var(--surface-2);color:var(--brand);font-weight:600}
.drawer__list .ic{width:26px;text-align:center;font-family:var(--ff-glyph);flex:none}
.drawer__foot{border-top:1px solid var(--line);padding:var(--sp-3) var(--sp-4) var(--sp-4);
  display:flex;flex-direction:column;gap:var(--sp-3)}
/* Legal + core links: one compact row, wrapping only if it truly has to. */
.drawer__legal{display:flex;flex-wrap:wrap;align-items:center;gap:6px;
  font-size:12.5px;font-weight:500;line-height:1.4}
.drawer__legal a{color:var(--muted);padding:2px 0}
.drawer__legal a:hover{color:var(--brand);text-decoration:none}
.drawer__legal span{color:var(--line)}
.drawer__util{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3)}
.social{display:flex;gap:var(--sp-2)}
.social a{width:36px;height:36px;display:grid;place-items:center;border-radius:var(--r-pill);
  background:var(--surface-2);font-size:15px}
.social:empty{display:none}
.hidden-empty:empty{display:none}

/* ---------------------------------------------------------------- footer, 3 columns */
/* No margin-top: the shell's bottom padding is the only gap, so the article flows
   straight into the footer instead of leaving a dead band above it. */
.ftr{background:var(--surface);border-top:1px solid var(--line);margin-top:0;
  padding:var(--sp-5) var(--sp-4)}
@media(min-width:820px){.ftr{padding:var(--sp-6) var(--sp-5) var(--sp-5)}}
.ftr__in{max-width:var(--shell-wide);margin:0 auto}
.ftr__cols{display:grid;gap:var(--sp-5);grid-template-columns:1fr}
@media(min-width:640px){.ftr__cols{grid-template-columns:repeat(2,minmax(0,1fr))}
  .ftr__brand{grid-column:1/-1}}
@media(min-width:900px){.ftr__cols{grid-template-columns:1.4fr 1fr 1fr;gap:var(--sp-7)}
  .ftr__brand{grid-column:auto}}

.ftr__logo{display:flex;align-items:center;gap:var(--sp-2);color:var(--text);
  font-family:var(--ff-head);font-weight:700;font-size:16px;letter-spacing:-.01em}
.ftr__logo:hover{text-decoration:none;color:var(--brand)}
.ftr__blurb{margin:var(--sp-3) 0 0;font-size:13.5px;line-height:1.7;color:var(--muted);max-width:44ch}

.ftr__h{font-family:var(--ff-head);font-size:13.5px;font-weight:700;letter-spacing:.1em;
  text-transform:uppercase;color:var(--primary-purple);margin:0 0 var(--sp-3);
  padding-bottom:var(--sp-2);border-bottom:1px solid var(--line)}
.ftr__list{list-style:none;margin:0;padding:0}
.ftr__list li{margin:0}
.ftr__list a{display:flex;align-items:center;gap:var(--sp-2);color:var(--muted);
  font-size:14px;padding:6px 0}
.ftr__list a:hover{color:var(--brand);text-decoration:none}
.ftr__list a[aria-current="page"]{color:var(--brand);font-weight:600}
.ftr__list .ic{width:20px;flex:none;text-align:center;font-family:var(--ff-glyph);
  font-size:13px;color:var(--primary-blue);opacity:.9}

.ftr__base{margin-top:var(--sp-5);padding-top:var(--sp-4);border-top:1px solid var(--line);
  display:flex;flex-direction:column;align-items:center;gap:6px;text-align:center;
  padding-right:64px;padding-left:8px}
@media(min-width:640px){.ftr__base{padding-right:8px}}
.ftr__copy,.ftr__note{margin:0;font-size:12.5px;line-height:1.6;color:var(--muted);max-width:60ch}
.ftr__note{opacity:.75}
.totop{position:fixed;right:14px;bottom:18px;z-index:35;width:44px;height:44px;border:0;
  border-radius:var(--r-pill);background:var(--surface);color:var(--brand);box-shadow:var(--sh-3);
  cursor:pointer;font-size:18px;opacity:0;visibility:hidden;transition:opacity var(--dur),visibility var(--dur)}
.totop.is-on{opacity:1;visibility:visible}

/* components.css */
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);
  padding:var(--sp-4);box-shadow:var(--sh-1);transition:box-shadow var(--dur) var(--ease),transform var(--dur) var(--ease)}
.card--link:hover{box-shadow:var(--sh-2);transform:translateY(-2px);text-decoration:none}
.panel{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:var(--sp-4);box-shadow:var(--sh-2)}
@media(min-width:820px){.panel{padding:var(--sp-5)}}

.btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--sp-2);
  min-height:44px;padding:0 var(--sp-5);border:1px solid transparent;border-radius:var(--r-pill);
  font-family:var(--ff-body);font-size:16.5px;font-weight:700;cursor:pointer;color:var(--text);
  background:var(--surface-2);letter-spacing:.005em;
  transition:transform var(--dur) var(--ease),box-shadow var(--dur) var(--ease),background var(--dur)}
.btn:hover{text-decoration:none}
.btn:active{transform:scale(.97)}
.btn[disabled]{opacity:.55;cursor:not-allowed}
.btn--primary{background:var(--brand-gradient);color:#fff;box-shadow:var(--sh-2);width:100%;
  font-size:17.5px;min-height:54px;text-shadow:var(--text-on-grad);letter-spacing:.01em}
.btn--primary:hover{background:var(--brand-gradient-hover);color:#fff;box-shadow:var(--sh-3)}
.btn--ghost{background:transparent;border-color:var(--line);color:var(--text)}
.btn--ghost:hover{background:var(--surface-2)}
/* Solid accent — for a secondary action that still deserves to be seen (Generate similar). */
.btn--accent{background:var(--brand-gradient);color:#fff;font-weight:700;box-shadow:var(--sh-1);
  text-shadow:var(--text-on-grad)}
.btn--accent:hover{background:var(--brand-gradient-hover);color:#fff;box-shadow:var(--sh-2)}
.btn--accent:active{background:var(--brand-gradient-hover)}
html[data-theme="dark"] .btn--accent,html[data-theme="dark"] .btn--accent:hover{color:#fff}
/* Clear: brand-tinted outline, filling in on hover. */
.btn--clear{background:transparent;border-color:var(--primary-blue);color:var(--primary-blue);font-weight:700}
.btn--clear:hover{background:var(--brand-gradient);border-color:transparent;color:#fff;text-shadow:var(--text-on-grad)}
.btn--clear:active{background:var(--brand-gradient-hover);border-color:transparent;color:#fff}
html[data-theme="dark"] .btn--clear:hover,html[data-theme="dark"] .btn--clear:active{color:#fff}
.btn--copy{background:var(--brand-gradient);color:#fff;min-height:38px;padding:0 var(--sp-4);
  font-size:15px;text-shadow:var(--text-on-grad)}
.btn--copy:hover{background:var(--brand-gradient-hover);color:#fff}
/* Copy bio is the primary action in the result row: taller, higher contrast. */
.btn--primary-sm{min-height:44px;font-size:16px;font-weight:700;box-shadow:var(--sh-2)}
.btn--primary-sm:hover{box-shadow:var(--sh-3)}
.btn--save{min-height:44px;font-size:17px;line-height:1}
.btn--save[aria-pressed="true"]{background:var(--brand-gradient);border-color:transparent;color:#fff}
.btn--sm{min-height:38px;padding:0 var(--sp-3);font-size:13.5px}
.btn--icon{width:38px;padding:0;min-height:38px}
.btn.is-loading{pointer-events:none}
.spin{width:16px;height:16px;border:2px solid rgba(255,255,255,.4);border-top-color:#fff;
  border-radius:50%;animation:spin .7s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
.btnrow{display:flex;flex-wrap:wrap;gap:var(--sp-2)}

.grid{display:grid;gap:var(--sp-3)}
.grid--2{grid-template-columns:repeat(2,minmax(0,1fr))}
@media(min-width:560px){.grid--sm2{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:820px){.grid--3{grid-template-columns:repeat(3,minmax(0,1fr))}
.grid--4{grid-template-columns:repeat(4,minmax(0,1fr))}}

.field{display:flex;flex-direction:column;gap:6px}
.field>label{font-size:12.5px;font-weight:600;color:var(--muted);letter-spacing:.01em}
.field select,.field input,.field textarea{width:100%;height:52px;padding:0 var(--sp-4);
  background:var(--surface);color:var(--text);border:1px solid var(--line);
  border-radius:var(--r-md);font:inherit;font-size:15px;transition:border-color var(--dur),box-shadow var(--dur)}
.field textarea{height:auto;min-height:120px;padding:var(--sp-3) var(--sp-4);line-height:1.7;resize:vertical}
.field select{appearance:none;-webkit-appearance:none;padding-right:40px;cursor:pointer;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%231E5CD9' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
  background-repeat:no-repeat;background-position:right 12px center}
html[data-theme="dark"] .field select{background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%236D96F5' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>")}
.field select:focus,.field input:focus,.field textarea:focus{outline:none;border-color:var(--brand);box-shadow:var(--ring)}

.chips{display:flex;gap:var(--sp-2);overflow-x:auto;scroll-snap-type:x proximity;
  padding:var(--sp-1) 0 var(--sp-3);margin:0;list-style:none;scrollbar-width:none}
.chips::-webkit-scrollbar{display:none}
.chip{scroll-snap-align:start;flex:none;display:inline-flex;align-items:center;gap:6px;
  min-height:38px;padding:0 var(--sp-4);border-radius:var(--r-pill);background:var(--surface);
  border:1px solid var(--line);color:var(--text);font-size:13.5px;font-weight:500;white-space:nowrap}
.chip:hover{border-color:var(--brand);text-decoration:none}
.chip.is-active,.chip[aria-current="page"]{background:var(--brand-gradient);border-color:transparent;
  color:#fff;text-shadow:var(--text-on-grad);font-weight:700}

.result{border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface-2);
  padding:var(--sp-4);min-height:150px;display:flex;flex-direction:column;gap:var(--sp-3)}
.result__text{font-family:var(--ff-glyph);white-space:pre-line;font-size:17px;line-height:1.9;
  font-weight:500;margin:0;word-break:break-word}
@media(min-width:820px){.result__text{font-size:18px}}
/* Result actions: centred counter framed by rules, then all three buttons in one row. */
.result__bar{display:flex;flex-direction:column;gap:var(--sp-3);margin-top:auto}
.result__count{display:flex;justify-content:center;padding:var(--sp-2) 0;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
/* .btn is overflow:hidden for the ripple, which zeroes a flex item's automatic minimum
   size, so a too-narrow button clips its label at BOTH ends with no ellipsis. A real
   flex-basis gives each button a comfortable minimum width and lets the row wrap before
   any label is squeezed. Do NOT reach for repeat(auto-fit,minmax(...)) here: combining an
   auto-repeat with any other intrinsic track (the Save button's `auto`) is invalid, and
   the parser drops the whole declaration, silently stacking the buttons. */
.result__acts{display:flex;flex-wrap:wrap;align-items:stretch;gap:var(--sp-2)}
.result__acts .btn{flex:1 1 auto;min-width:max-content;padding:0 var(--sp-3);white-space:nowrap}
.result__acts .btn--save{flex:0 0 auto;padding:0 var(--sp-4)}
/* Keep all three on one line even on a narrow phone: below ~26rem of available width the
   accent button drops to a shorter label rather than the row wrapping. Container query,
   not a media query — the panel can be narrower than the viewport. */
.result{container-type:inline-size}
.lbl-short{display:none}
@container (max-width:25.5rem){
  .lbl-full{display:none}
  .lbl-short{display:inline}
  .result__acts .btn{padding:0 var(--sp-2)}
}
@supports not (container-type:inline-size){
  @media(max-width:460px){
    .lbl-full{display:none}
    .lbl-short{display:inline}
    .result__acts .btn{padding:0 var(--sp-2)}
  }
}
.count{font-family:var(--ff-mono);font-size:13px;font-weight:600;color:var(--ok);
  letter-spacing:.02em}
.count.is-over{color:var(--danger)}
.tag{display:inline-block;font-size:11.5px;font-weight:600;letter-spacing:.04em;
  text-transform:uppercase;color:var(--muted);background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-pill);padding:3px 9px}
.tag--limited{color:var(--coral);border-color:var(--coral)}
.tag--medium{color:var(--amber);border-color:var(--amber)}
.tag--high{color:var(--accent);border-color:var(--accent)}

/* Result and frame cards: preview on the left, actions and meta stacked on the right.
   The bar is a fixed-width column so every card in a grid lines its buttons up, and the
   preview takes the remaining space. */
.biocard{display:flex;flex-direction:row;align-items:flex-start;gap:var(--sp-3);
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);
  padding:var(--sp-4);box-shadow:var(--sh-1)}
.biocard__text{flex:1 1 auto;min-width:0;font-family:var(--ff-glyph);white-space:pre-line;
  font-size:16px;line-height:1.9;margin:0;word-break:break-word}
.biocard__bar{flex:0 0 auto;display:flex;flex-direction:column;align-items:flex-end;
  gap:var(--sp-2);margin:0}

.nickcard{display:flex;flex-direction:row;align-items:center;gap:var(--sp-3);
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);
  padding:var(--sp-3) var(--sp-4);box-shadow:var(--sh-1)}
.nickcard__name{flex:1 1 auto;min-width:0;font-family:var(--ff-glyph);font-size:19px;
  line-height:1.6;word-break:break-word;font-weight:500}
.nickcard__bar{flex:0 0 auto;display:flex;flex-direction:column;align-items:flex-end;gap:6px}

/* The meta row inside the right column: count then favourite, side by side. */
.card__meta{display:flex;align-items:center;gap:6px;justify-content:flex-end}
.btn--fav{width:34px;min-height:34px;padding:0;font-size:15px;line-height:1;
  background:transparent;border-color:var(--line);color:var(--muted)}
.btn--fav:hover{border-color:var(--primary-blue);color:var(--primary-blue)}
.btn--fav[aria-pressed="true"]{background:var(--brand-gradient);border-color:transparent;
  color:#fff;text-shadow:var(--text-on-grad)}

/* Very narrow viewports: let the right column drop under the preview rather than
   squeezing the frame, which would break long decorated names mid-glyph. */
@media(max-width:400px){
  .biocard,.nickcard{flex-wrap:wrap}
  .biocard__bar,.nickcard__bar{flex-direction:row;align-items:center;width:100%;
    justify-content:flex-end}
}
.nickcard.is-flip{animation:flip .42s var(--ease)}
@keyframes flip{0%{transform:rotateX(-90deg);opacity:0}100%{transform:rotateX(0);opacity:1}}

.toast{position:fixed;left:50%;bottom:24px;transform:translate(-50%,20px);z-index:90;
  background:var(--text);color:var(--bg);padding:10px var(--sp-4);border-radius:var(--r-pill);
  font-size:14px;font-weight:600;box-shadow:var(--sh-3);opacity:0;visibility:hidden;
  transition:opacity 180ms,transform 180ms,visibility 180ms}
.toast.is-on{opacity:1;visibility:visible;transform:translate(-50%,0)}

.modal{position:fixed;inset:0;z-index:80;display:grid;place-items:center;padding:var(--sp-4);
  background:rgba(11,13,24,.6);opacity:0;visibility:hidden;transition:opacity var(--dur),visibility var(--dur)}
.modal.is-open{opacity:1;visibility:visible}
.modal__box{background:var(--surface);border-radius:var(--r-lg);padding:var(--sp-5);
  max-width:420px;width:100%;box-shadow:var(--sh-3)}

.faq{border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface);
  padding:0 var(--sp-4);margin-bottom:var(--sp-2)}
.faq summary{cursor:pointer;list-style:none;padding:var(--sp-4) 0;font-family:var(--ff-head);
  font-weight:600;font-size:15.5px;display:flex;gap:var(--sp-3);justify-content:space-between;align-items:flex-start}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"+";color:var(--brand);font-size:20px;line-height:1;flex:none}
.faq[open] summary::after{content:"\2212"}
.faq[open] summary{border-bottom:1px solid var(--line)}
.faq__a{padding:var(--sp-4) 0 var(--sp-2)}
.faq__a p:last-child{margin-bottom:0}

.skel{background:linear-gradient(90deg,var(--surface-2) 25%,var(--line) 37%,var(--surface-2) 63%);
  background-size:400% 100%;animation:shimmer 1.3s ease-in-out infinite;border-radius:var(--r-md);min-height:96px}
@keyframes shimmer{0%{background-position:100% 0}100%{background-position:0 0}}
.fade-in{animation:fadein .28s var(--ease)}
@keyframes fadein{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}

.crumbs{display:none}

/* ------------------------------------------------------------------ chunk loader
   The branded Load More sits centred under a chunked list. It owns the spinner while a
   batch is appending, so the tap always has visible feedback. */
.chunk{display:flex;flex-direction:column;align-items:center;gap:var(--sp-2);
  margin-top:var(--sp-5)}
.chunk__status{margin:0;font-size:13px;color:var(--muted);font-variant-numeric:tabular-nums}
.btn--load{background:var(--brand-gradient);color:#fff;font-weight:700;min-height:52px;
  padding:0 var(--sp-7);font-size:17px;box-shadow:var(--sh-2);text-shadow:var(--text-on-grad);
  min-width:min(20rem,100%)}
.btn--load:hover{background:var(--brand-gradient-hover);color:#fff;box-shadow:var(--sh-3)}
.btn--load:active{transform:scale(.975)}
.btn--load.is-loading{pointer-events:none;opacity:.9}
.btn--load .spin{border-color:rgba(255,255,255,.45);border-top-color:#fff}
@media(prefers-reduced-motion:reduce){.btn--load:active{transform:none}}

/* pages.css */
/* Page head: centred title + a tight 2-3 line description. Used by the homepage hero and
   by every category and tool page, so subpages read like app screens rather than
   documents. The accent rules run the full viewport width, which is why they are
   pseudo-elements rather than borders on the (max-760px) shell. */
.hero{padding:var(--sp-2) 0 var(--sp-3);text-align:center;position:relative}
@media(min-width:820px){.hero{padding:var(--sp-3) 0 var(--sp-4)}}
.hero::before,.hero::after{content:"";position:absolute;left:50%;transform:translateX(-50%);
  width:100vw;height:1px;pointer-events:none;
  background:linear-gradient(90deg,transparent,var(--line) 14%,var(--line) 86%,transparent)}
.hero::before{top:0}
.hero::after{bottom:0}
.hero h1{margin-bottom:6px}
.hero p{color:var(--muted);font-size:14.5px;max-width:46ch;margin:0 auto var(--sp-2);line-height:1.55}
@media(min-width:820px){.hero p{font-size:15.5px;max-width:52ch}}
.hero .trust{margin-bottom:0}
.hero>*:last-child{margin-bottom:0}
.trust{display:flex;flex-wrap:wrap;justify-content:center;gap:4px var(--sp-3);
  font-size:11.5px;font-weight:600;color:var(--muted);list-style:none;padding:0;margin:0}
@media(min-width:820px){.trust{font-size:12.5px;gap:6px var(--sp-4)}}
.trust li{display:flex;align-items:center;gap:6px;margin:0}
.trust .dot{width:6px;height:6px;border-radius:50%;background:var(--accent)}

/* Compact option grid: two columns on phones, three on wide screens. Style spans the
   row, Font style and Birth date always sit side by side, and the name input is the
   full-width bottom row. */
.gen__grid{display:grid;gap:var(--sp-3);grid-template-columns:repeat(2,minmax(0,1fr))}
@media(min-width:900px){.gen__grid{grid-template-columns:repeat(3,minmax(0,1fr))}}
.gen__grid .field--full{grid-column:1/-1}
.gen__grid .field--half{grid-column:auto}
.gen__note{font-size:12.5px;color:var(--muted);margin:var(--sp-2) 0 0}

.ig{max-width:360px;margin:0 auto;background:var(--surface);border:1px solid var(--line);
  border-radius:26px;padding:var(--sp-4) var(--sp-4) var(--sp-3);box-shadow:var(--sh-3);overflow:hidden}
.ig__bar{display:flex;align-items:center;justify-content:space-between;font-size:13px;
  color:var(--muted);font-family:var(--ff-mono);margin-bottom:var(--sp-3)}
.ig__top{display:flex;align-items:center;gap:var(--sp-4)}
.ig__av{width:74px;height:74px;border-radius:50%;flex:none;padding:3px;background:var(--grad-brand)}
.ig__av span{display:grid;place-items:center;width:100%;height:100%;border-radius:50%;
  background:var(--surface-2);font-size:24px;font-family:var(--ff-glyph)}
.ig__stats{display:flex;flex:1;justify-content:space-around;text-align:center}
.ig__stats b{display:block;font-family:var(--ff-head);font-size:15px}
.ig__stats span{font-size:12px;color:var(--muted)}
.ig__name{font-weight:700;font-size:14.5px;margin:var(--sp-3) 0 2px;display:flex;align-items:center;gap:4px}
.ig__name>[data-ig-name]{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ig__verified{display:inline-flex;align-items:center;flex:0 0 auto;width:1em;height:1em;
  font-size:14.5px;position:relative;top:.5px}
.ig__verified svg{display:block;width:100%;height:100%;overflow:visible;shape-rendering:geometricPrecision}
.ig__verified .disc{fill:#3897F0;stroke:none}
.ig__verified .tick{fill:none;stroke:#fff;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;
  vector-effect:non-scaling-stroke}
.ig__cat{font-size:12.5px;color:var(--muted);margin:0 0 6px}
.ig__bio{font-family:var(--ff-glyph);white-space:pre-line;font-size:14px;line-height:1.55;
  margin:0;word-break:break-word;min-height:66px}
.ig__warn{font-size:12px;color:var(--coral);margin:6px 0 0;font-weight:600}
.ig__btns{display:grid;grid-template-columns:1fr 1fr auto;gap:6px;margin-top:var(--sp-4)}
.ig__btns b,.ig__btns i{height:32px;display:grid;place-items:center;border-radius:var(--r-sm);
  font-size:12.5px;font-weight:600;font-style:normal}
.ig__btns b:first-child{background:var(--brand);color:#fff}
.ig__btns b:nth-child(2),.ig__btns i{background:var(--surface-2);color:var(--text)}
.ig__btns i{width:34px}
/* Story highlights: dual-ring circles, emoji centred, label beneath. */
.ig__hl{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--sp-2);margin-top:var(--sp-4)}
.ig__hl div{text-align:center;font-size:11.5px;color:var(--text);min-width:0}
.ig__hl div span{display:grid;place-items:center;width:56px;height:56px;margin:0 auto 6px;
  border-radius:50%;background:var(--surface);
  border:1px solid var(--line);box-shadow:0 0 0 3px var(--surface),0 0 0 4px var(--line);
  font-size:23px;line-height:1}
.ig__hl div b{display:block;font-weight:400;font-size:12.5px;color:var(--text);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* Profile tab strip: grid active, reels + tagged muted. Bleeds to the card edges, so the
   divider rules run full width the way they do on a real profile. */
.ig__tabs{display:grid;grid-template-columns:repeat(3,1fr);margin:var(--sp-4) calc(var(--sp-4) * -1) 0;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.ig__tabs span{display:grid;place-items:center;height:40px}
.ig__tabs svg{width:22px;height:22px;fill:none;stroke:var(--muted);stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round;opacity:.55}
.ig__tabs .is-active svg{stroke:var(--text);stroke-width:2;opacity:1}

/* Compact 3-up post row: pastel blocks, no gaps, short by design. */
.ig__grid{display:grid;grid-template-columns:repeat(3,1fr);gap:0;
  margin:0 calc(var(--sp-4) * -1)}
.ig__grid i{aspect-ratio:1;display:block;font-style:normal}
.ig__mark{margin:var(--sp-3) 0 0;text-align:center;font-size:11px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--muted);opacity:.5}

.catcard{display:flex;gap:var(--sp-3);align-items:flex-start;color:var(--text)}
.catcard .ic{width:40px;height:40px;flex:none;border-radius:11px;background:var(--surface-2);
  display:grid;place-items:center;font-size:19px;font-family:var(--ff-glyph)}
.catcard h3{margin:0 0 2px;font-size:15.5px}
.catcard p{margin:0;font-size:13px;color:var(--muted);line-height:1.5}
.catcard .n{font-family:var(--ff-mono);font-size:11.5px;color:var(--brand);font-weight:600}

.toolcard{display:block;color:var(--text)}
.toolcard .ic{font-size:22px;margin-bottom:var(--sp-2);font-family:var(--ff-glyph)}
.toolcard h3{margin:0 0 4px;font-size:15.5px}
.toolcard p{margin:0;font-size:13px;color:var(--muted);line-height:1.5}

/* 16:9 everywhere a cover image appears: 1200×675 uploads drop straight in. */
.postcard{display:flex;flex-direction:column;color:var(--text);overflow:hidden;padding:0}
.postcard img,.postcard .ph{aspect-ratio:16/9;width:100%;height:auto;object-fit:cover;
  object-position:center;background:var(--surface-2);display:block}
.postcard__b{padding:var(--sp-4)}
.postcard h3{font-size:15.5px;margin:0 0 6px}
.postcard p{margin:0;font-size:13px;color:var(--muted);line-height:1.55}
/* Post header image. Same ratio contract as the cards. */
.posthero{aspect-ratio:16/9;width:100%;height:auto;object-fit:cover;object-position:center;
  border-radius:var(--r-md);margin:var(--sp-3) 0 var(--sp-4);display:block;overflow:hidden}
.ph{display:grid;place-items:center;color:var(--muted);font-family:var(--ff-mono);font-size:11.5px;
  text-align:center;padding:var(--sp-3);
  background-image:repeating-linear-gradient(45deg,var(--surface-2) 0 8px,var(--bg) 8px 16px)}

.sect__head{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-3);
  margin-bottom:var(--sp-4);padding-top:var(--sp-4);position:relative}
.sect__head::before{content:"";position:absolute;top:0;left:50%;transform:translateX(-50%);
  width:100vw;height:1px;pointer-events:none;
  background:linear-gradient(90deg,transparent,var(--line) 14%,var(--line) 86%,transparent)}
.sect__head h2{margin:0}
.sect__head a{font-size:13.5px;font-weight:600;flex:none}
.feed{display:grid;gap:var(--sp-3)}
@media(min-width:700px){.feed--2{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:700px){.feed--nick{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:1000px){.feed--nick{grid-template-columns:repeat(3,minmax(0,1fr))}}
.feed[data-reserve]{min-height:420px}
.center{text-align:center}
/* "Your recent bios" reads as a bar of its own, framed top and bottom. */
.sect__head--bar{padding:var(--sp-3) 0;margin-bottom:var(--sp-4);
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);align-items:center}
.sect__head--bar::before{display:none}
.sect__head--bar h2{font-size:17px}
@media(min-width:820px){.sect__head--bar h2{font-size:20px}}
/* Clearing history fades and collapses rather than snapping out. */
[data-recent]{overflow:hidden}
[data-recent].is-clearing{animation:collapseOut 320ms var(--ease) forwards}
@keyframes collapseOut{
  0%{opacity:1;transform:none}
  45%{opacity:0;transform:translate3d(0,-6px,0)}
  100%{opacity:0;transform:translate3d(0,-6px,0);max-height:0;margin-top:0;padding:0}
}
@media(prefers-reduced-motion:reduce){[data-recent].is-clearing{animation:none}}
.fontrow{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-3) 0;border-bottom:1px solid var(--line)}
.fontrow__t{flex:1;font-family:var(--ff-glyph);font-size:18px;word-break:break-word}
.fontrow__n{font-size:11.5px;color:var(--muted);font-family:var(--ff-mono);width:96px;flex:none}
.symgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(52px,1fr));gap:6px}
.symgrid button{aspect-ratio:1;border:1px solid var(--line);background:var(--surface);
  border-radius:var(--r-sm);font-family:var(--ff-glyph);font-size:19px;cursor:pointer;color:var(--text)}
.symgrid button:hover{border-color:var(--brand);background:var(--surface-2)}
.gauge{height:8px;border-radius:var(--r-pill);background:var(--surface-2);overflow:hidden;margin:var(--sp-3) 0}
.gauge i{display:block;height:100%;background:var(--grad-cta);width:0;transition:width var(--dur) var(--ease)}
.cut{background:rgba(255,107,87,.18);border-radius:3px}
/* In-article CTA: centred card, lifts on hover. */
.cta-inline{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:var(--sp-5) var(--sp-4);margin:var(--sp-5) auto;max-width:32rem;
  display:flex;flex-direction:column;align-items:center;gap:var(--sp-3);text-align:center;
  box-shadow:var(--sh-1);
  transition:box-shadow var(--dur) var(--ease),transform var(--dur) var(--ease),border-color var(--dur)}
.cta-inline:hover{box-shadow:var(--sh-2);transform:translateY(-2px);border-color:var(--brand)}
.cta-inline p{margin:0;font-weight:600;font-size:15.5px;max-width:26ch}
.seo>.cta-inline:last-child{margin-bottom:0}
@media(prefers-reduced-motion:reduce){.cta-inline:hover{transform:none}}
.toc{background:var(--surface-2);border-radius:var(--r-md);padding:var(--sp-4);margin-bottom:var(--sp-5)}
.toc ol{margin:0;padding-left:1.2em}
.toc li{margin-bottom:4px;font-size:14px}

/* motion.css — view transitions, ripple, press feedback.
   Everything animates transform/opacity only, so it stays on the compositor. */
main{will-change:auto}
main[data-view-enter]{animation:viewIn 260ms var(--ease) both}
main[data-view-enter="back"]{animation-name:viewInBack}
main[data-view-exit]{animation:viewOut 150ms var(--ease) both;pointer-events:none}
main[data-view-exit="back"]{animation-name:viewOutBack}
@keyframes viewIn{from{opacity:0;transform:translate3d(22px,0,0)}to{opacity:1;transform:none}}
@keyframes viewOut{from{opacity:1;transform:none}to{opacity:0;transform:translate3d(-14px,0,0)}}
@keyframes viewInBack{from{opacity:0;transform:translate3d(-22px,0,0)}to{opacity:1;transform:none}}
@keyframes viewOutBack{from{opacity:1;transform:none}to{opacity:0;transform:translate3d(14px,0,0)}}

/* Category switch inside a view: cards slide in from the right, lightly staggered. */
.feed>*,.grid>*{animation:cardIn 300ms var(--ease) both}
.feed>*:nth-child(1),.grid>*:nth-child(1){animation-delay:0ms}
.feed>*:nth-child(2),.grid>*:nth-child(2){animation-delay:24ms}
.feed>*:nth-child(3),.grid>*:nth-child(3){animation-delay:48ms}
.feed>*:nth-child(4),.grid>*:nth-child(4){animation-delay:72ms}
.feed>*:nth-child(5),.grid>*:nth-child(5){animation-delay:88ms}
.feed>*:nth-child(n+6),.grid>*:nth-child(n+6){animation-delay:104ms}
@keyframes cardIn{from{opacity:0;transform:translate3d(28px,0,0)}to{opacity:1;transform:none}}
.feed.is-leaving>*{animation:cardOut 160ms var(--ease) both}
@keyframes cardOut{from{opacity:1;transform:none}to{opacity:0;transform:translate3d(-20px,0,0)}}

/* Press feedback. Scale is small on purpose — enough to feel, not enough to wobble. */
.btn,.chip,.card--link,.iconbtn,.symgrid button,.totop{
  -webkit-tap-highlight-color:transparent;touch-action:manipulation;
  transition:transform 140ms var(--ease),box-shadow var(--dur) var(--ease),
             background-color var(--dur) var(--ease),border-color var(--dur) var(--ease),color var(--dur) var(--ease)}
.btn.is-pressed,.chip.is-pressed,.symgrid button.is-pressed{transform:scale(.965)}
.card--link.is-pressed{transform:scale(.988)}
.iconbtn.is-pressed,.totop.is-pressed{transform:scale(.9)}
.btn--primary.is-pressed{transform:scale(.985)}
.btn,.chip,.card--link,.symgrid button{position:relative;overflow:hidden}
.ink{position:absolute;border-radius:50%;pointer-events:none;background:currentColor;
  opacity:.18;transform:scale(0);animation:ink 520ms var(--ease) forwards}
.btn--primary .ink,.btn--copy .ink,.btn--accent .ink{background:#fff;opacity:.3}
@keyframes ink{to{transform:scale(1);opacity:0}}

/* Routing state: keep taps from queueing while a view swaps. */
.is-routing main{pointer-events:none}
.is-routing .hdr,.is-routing .drawer{pointer-events:auto}

@media(prefers-reduced-motion:reduce){
  main[data-view-enter],main[data-view-exit],.feed>*,.grid>*,.feed.is-leaving>*{animation:none}
  .ink{display:none}
  .btn.is-pressed,.chip.is-pressed,.card--link.is-pressed,.iconbtn.is-pressed{transform:none}
}
