/*
 * The Rails Guild, Console Ledger design system.
 * Replaces the scaffold application.css entirely. Propshaft-ready, no preprocessing.
 * Load order inside this file matters: tokens, then element base, then components.
 * Webfonts are declared in fonts.css (vendored woff2, see HANDOFF.md step 1).
 */
/* ===== colors.css ===== */
/* The Rails Guild tokens, v3 "Console Ledger": black leather, engraved gold, ruby verification gems. Variable names kept stable across versions. */
:root{
/* Base surfaces (dark) */
--parchment:#0e0b07;--parchment-deep:#1a1409;--parchment-bright:#171106;--parchment-shadow:#000;
--line:rgba(212,164,55,.28);--line-strong:#8a681f;
--ink:#f0e6d0;--ink-soft:#c4b28c;--ink-faint:#8a7a58;
/* Gold, the accent */
--wax:#d4a437;--wax-dark:#8a681f;--wax-bright:#f2ce74;
--gold:#a8863c;--gold-dark:#6f5518;--gold-bright:#e9c467;
/* Ruby: the alert flash and the errors box, the two things that say "wrong" */
--ruby:#c9163f;--ruby-dark:#8f0e2b;--ruby-bright:#ff5f7e;
/* Moss: the verified mark and the notice flash, the two things that say "good" */
--moss:#4caf6a;--moss-dark:#2e7a45;
/* Semantic */
--surface-page:var(--parchment);--surface-card:var(--parchment-bright);--surface-inset:var(--parchment-deep);
--text-body:var(--ink);--text-muted:var(--ink-soft);--text-faint:var(--ink-faint);--text-on-wax:#171006;
--accent:var(--wax);--accent-hover:var(--wax-bright);
--link:var(--wax);--link-hover:var(--wax-bright);
--border-default:var(--line);--border-strong:var(--line-strong);--border-ink:var(--gold);
--verified:var(--moss);--verified-bright:var(--moss);--unverified:var(--ink-faint);
--flash-notice-bg:var(--parchment-deep);--flash-notice-border:var(--moss);
--flash-alert-bg:var(--parchment-deep);--flash-alert-border:var(--ruby);
--error-text:var(--ruby-bright);
--focus-ring:var(--wax);
--glow:rgba(212,164,55,.45);--glow-soft:rgba(212,164,55,.22);--glow-ruby:rgba(225,29,72,.45);--glow-moss:rgba(76,175,106,.45);
/* Globe: read by the canvas, so the theme still owns every colour on it. */
--globe-ocean:#1a1409;--globe-land:#a8863c;--globe-grid:rgba(212,164,55,.14);
--globe-dot:#c9163f;--globe-halo:rgba(255,95,126,.6);
}
/* Native widgets are drawn by the browser, not by us, and without this they are
   drawn light: a select's popup came up white while its options inherited our
   pale ink, which is how the "deployed with" menu ended up unreadable. Scrollbars
   and date pickers follow the same switch. */
:root{color-scheme:dark}

/* Light theme: same gold-and-ruby system on warm paper. Set data-theme="light" on <html>. */
[data-theme="light"]{
color-scheme:light;
--parchment:#faf6ea;--parchment-deep:#f1e9d2;--parchment-bright:#fffdf5;--parchment-shadow:#e6dcbf;
--line:rgba(138,104,31,.3);--line-strong:#8a681f;
--ink:#241c0e;--ink-soft:#5c4e2e;--ink-faint:#8a7a58;
--wax:#8a681f;--wax-dark:#6f5518;--wax-bright:#a8863c;
--gold:#8a681f;--gold-dark:#6f5518;--gold-bright:#6f5518;
--ruby:#b0102f;--ruby-dark:#8f0e2b;--ruby-bright:#8f0e2b;
--moss:#2e7a45;--moss-dark:#1f5a31;
--text-on-wax:#fffdf5;
--glow:rgba(168,134,60,.35);--glow-soft:rgba(168,134,60,.18);--glow-ruby:rgba(176,16,47,.25);--glow-moss:rgba(46,122,69,.25);
--globe-ocean:#f1e9d2;--globe-land:#8a681f;--globe-grid:rgba(138,104,31,.2);
--globe-dot:#b0102f;--globe-halo:rgba(176,16,47,.55);
}

/* ===== typography.css ===== */
/* IBM Plex Mono everywhere, the dev-guild voice. Georgia retained only as a fallback stack. */
:root{
--font-serif:Georgia,'Times New Roman',serif;
--font-mono:'IBM Plex Mono',ui-monospace,'SF Mono',Menlo,Consolas,monospace;
--font-rank:var(--font-mono);
--text-xs:.7rem;--text-sm:.8rem;--text-md:.95rem;--text-lg:1.05rem;--text-xl:1.35rem;--text-2xl:2rem;--text-3xl:2.6rem;
/* Title over content: a named thing (member, app, patron) is a 600-weight
   title at --text-title with its copy beneath at --text-content in muted ink.
   Content sits between sm and md on purpose: sm is chrome, md is prose. */
--text-title:var(--text-lg);--text-content:.875rem;
--leading-tight:1.25;--leading-body:1.6;
--tracking-caps:.08em;
--letterpress:none; /* @kind other */
--letterpress-deep:none; /* @kind other */
}

/* ===== spacing.css ===== */
:root{
--space-1:.25rem;--space-2:.5rem;--space-3:.75rem;--space-4:1rem;--space-5:1.5rem;--space-6:2rem;--space-7:3rem;--space-8:4rem;
--radius-sm:0;--radius-md:2px;--radius-full:50%;
--measure:38rem;--page-max:64rem;
}

/* ===== effects.css ===== */
:root{
/* Flat frames + gem glow. Gold hairlines are the structure; glow is reserved for gems and focus. */
--shadow-card:none;
--shadow-inset:none;
/* The 1px rim keeps the silhouette's edges reading at full width on the black ground. */
--seal-rim:drop-shadow(0 0 1px var(--gold)) drop-shadow(0 0 1px var(--gold));
--seal-glow:var(--seal-rim) drop-shadow(0 0 6px rgba(0,0,0,.6)) drop-shadow(0 0 7px var(--glow));
/* The crest's exact silhouette, traced from logo.png; percentages scale with the seal box. */
--seal-shape:polygon(50.00% 0.00%,56.53% 3.83%,62.13% 6.23%,69.22% 8.63%,77.99% 10.70%,83.77% 11.66%,90.86% 12.46%,100.00% 12.94%,100.00% 37.38%,99.25% 46.49%,97.76% 53.83%,96.46% 58.15%,92.91% 66.29%,89.74% 71.57%,85.26% 77.32%,80.60% 82.11%,75.93% 86.10%,71.08% 89.62%,63.62% 94.09%,57.46% 97.12%,49.63% 100.00%,43.84% 97.76%,35.07% 93.45%,30.04% 90.42%,23.32% 85.62%,18.47% 81.31%,13.81% 76.36%,11.38% 73.32%,7.65% 67.57%,5.04% 62.30%,2.99% 56.87%,1.49% 51.28%,0.56% 46.01%,0.00% 40.42%,0.00% 12.94%,13.81% 11.98%,21.08% 10.86%,28.17% 9.27%,38.99% 5.75%,45.15% 2.88%);
--rule-major:1px solid var(--gold);--rule-double:1px solid var(--gold);--rule-hairline:1px solid var(--line);
--focus-outline:1px solid var(--focus-ring);
}

/* ===== base.css ===== */
*{box-sizing:border-box}
body{margin:0;color:var(--text-muted);font-family:var(--font-mono);font-size:var(--text-content);line-height:var(--leading-body);background:var(--parchment)}
/* Emphasis has to climb back out of the muted ink to read as emphasis. */
strong{color:var(--text-body)}
h1,h2,h3,h4{font-family:var(--font-mono);font-weight:600;line-height:var(--leading-tight);color:var(--text-body);margin:0 0 var(--space-3)}
h1{font-size:var(--text-2xl)}
h2{font-size:var(--text-lg);text-transform:uppercase;letter-spacing:.08em}
h2::before{content:"// ";color:var(--gold)}
h3{font-size:var(--text-title)}
p{margin:0 0 var(--space-3)}
a{color:var(--link);text-decoration:underline;text-decoration-color:var(--line);text-underline-offset:2px}
a:hover{color:var(--link-hover);text-decoration-color:currentColor}
.muted{color:var(--text-muted)}
code{font-family:var(--font-mono);font-size:.85em;background:var(--surface-inset);border:var(--rule-hairline);border-radius:var(--radius-md);padding:.1em .35em;color:var(--text-muted)}
small{font-size:var(--text-sm);color:var(--text-faint)}
hr{border:0;border-top:var(--rule-major);margin:var(--space-5) 0}
:focus-visible{outline:var(--focus-outline);outline-offset:2px}
::selection{background:var(--wax);color:var(--parchment)}
label{display:inline-block;font-family:var(--font-mono);font-size:var(--text-xs);color:var(--text-muted);letter-spacing:.04em;text-transform:lowercase}
input[type="text"],input[type="email"],input[type="search"],input[type="url"],input[type="number"],textarea,select{font-family:var(--font-mono);font-size:var(--text-sm);color:var(--text-body);background:transparent;border:1px solid var(--line);border-radius:0;padding:var(--space-2) var(--space-3);width:100%;max-width:var(--measure)}
/* Explicit rather than transparent: a transparent select renders its own popup
   against the browser's default white in some engines, whatever the scheme says. */
select{background-color:var(--surface-page)}
option{background-color:var(--surface-page);color:var(--text-body)}
input::placeholder,textarea::placeholder{color:var(--text-faint);opacity:1}
input:focus-visible,textarea:focus-visible,select:focus-visible{outline:1px solid var(--gold);outline-offset:0}
input[type="checkbox"]{width:1rem;height:1rem;accent-color:var(--wax)}
input[type="file"]{font-family:var(--font-mono);font-size:var(--text-sm)}
/* Consent sits outside the lowercase label convention: it is a legal notice and
   has to read as written. */
.consent{max-width:var(--measure)}
.consent label{display:inline;text-transform:none;letter-spacing:normal;font-size:var(--text-sm);color:var(--text-body);line-height:1.5}

/* ===== guild.css ===== */
/* Guild components, Console Ledger. */
.button,button,input[type="submit"]{display:inline-block;font-family:var(--font-mono);font-weight:600;font-size:var(--text-sm);color:var(--gold-bright);background:transparent;border:1px solid var(--gold);border-radius:0;padding:var(--space-2) var(--space-4);cursor:pointer;text-decoration:none;text-transform:lowercase;white-space:nowrap;line-height:1.3}
.button:hover,button:hover,input[type="submit"]:hover{background:var(--gold);color:var(--parchment)}
.button--secondary{color:var(--text-muted);border-color:var(--line)}
.button--secondary:hover{background:transparent;border-color:var(--gold);color:var(--gold-bright)}
.button--quiet{color:var(--text-faint);border-color:transparent;padding-left:0;padding-right:0;font-weight:400;text-transform:none;text-decoration:underline;text-decoration-color:var(--line)}
.button--quiet:hover{background:transparent;color:var(--gold-bright)}
/* Chrome */
.page{max-width:var(--page-max);margin:0 auto;padding:0 var(--space-5)}
.site-header{display:flex;justify-content:space-between;align-items:baseline;gap:1rem;padding:var(--space-4) 0;border-bottom:1px solid var(--gold)}
.site-header nav{display:flex;gap:1rem;align-items:baseline}
.site-header__brand{font-family:var(--font-mono);font-size:1rem;font-weight:600;color:var(--text-body);text-decoration:none}
.site-header__brand{display:inline-flex;align-items:center;gap:.5em;white-space:nowrap}
.site-header__brand:hover{color:var(--gold-bright)}
.site-header nav a{color:var(--text-muted);text-decoration:none;font-size:var(--text-sm);padding:var(--space-2) 0;white-space:nowrap}
.site-header nav a:hover{color:var(--gold-bright)}
.site-header nav form{display:inline}
.site-header nav button{background:none;border:0;padding:var(--space-2) 0;margin:0;color:var(--text-muted);font-weight:400;text-transform:none;font-size:var(--text-sm);cursor:pointer;white-space:nowrap}
.site-header nav button:hover{background:none;color:var(--gold-bright)}
.site-header__logo{height:1.5em;width:auto;vertical-align:middle}
.site-footer{margin-top:var(--space-8);padding:var(--space-5) 0;border-top:var(--rule-hairline);color:var(--text-faint)}
.site-footer small{color:var(--text-faint);font-size:var(--text-xs)}
.site-footer__patrons{display:flex;flex-wrap:wrap;column-gap:var(--space-4);row-gap:var(--space-1);font-size:var(--text-xs);margin-bottom:var(--space-4)}
.site-footer__patrons span{color:var(--gold);letter-spacing:.04em}
.site-footer__patrons a{color:var(--text-faint);text-decoration-color:var(--line)}
.site-footer__patrons a:hover{color:var(--gold-bright)}
.site-footer__patrons a:last-child{color:var(--text-muted);font-style:italic}
.site-footer__links{display:flex;gap:var(--space-4);font-size:var(--text-xs);margin-bottom:var(--space-3)}
.site-footer__links a{color:var(--text-faint);text-decoration-color:var(--line)}
.site-footer__links a:hover{color:var(--gold-bright)}
/* Fine print; muted rather than faint because it sits below 12px. */
.site-footer__disclaimer small{font-size:.6rem;color:var(--text-muted)}
/* Patrons page: the same ten plaques, gallery-hung */
.patrons-page{margin-top:var(--space-6)}
.patrons-page>p{max-width:var(--measure)}
.patrons{display:grid;grid-template-columns:repeat(auto-fill,minmax(13rem,1fr));grid-auto-rows:1fr;gap:var(--space-4);margin:var(--space-5) 0 var(--space-6)}
/* Long-form pages: legal, about. One reading measure. */
.legal,.about{margin-top:var(--space-6);max-width:var(--measure)}
.about__signoff{margin-top:var(--space-5);margin-bottom:var(--space-2)}
/* White ink on transparency, drawn for the black page. The light theme is
   dormant (nothing sets data-theme yet), so flip it there rather than ship
   an invisible signature the day that theme lands. */
.signature{display:block;height:6rem;width:auto}
.about__name{margin-top:var(--space-2)}
:root[data-theme="light"] .signature{filter:invert(1)}
.legal h2{margin-top:var(--space-6)}
.legal ul{padding-left:var(--space-5)}
.legal li{margin-bottom:var(--space-2)}
/* Hero: a boxed frame with a starship prompt */
.hero{border:1px solid var(--gold);margin-top:var(--space-5);padding:var(--space-6) var(--space-4);text-align:center}
.hero h1{font-size:var(--text-2xl)}
.hero__mark{margin:0 auto var(--space-3)}
.hero__mark img{height:110px;width:auto}

.hero p{max-width:var(--measure);margin:0 auto var(--space-4);color:var(--text-muted)}
.hero__tagline{font-size:var(--text-lg);color:var(--text-body);margin-bottom:var(--space-2)}
.hero__sub{font-size:var(--text-sm);color:var(--text-muted)}
/* Flash */
/* Says a condition the member has to act on, above the form rather than under
   it. Framed like a flash, but it belongs to the page and outlives a redirect. */
/* The fixed head of an invitation email, shown on the compose page above the
   message it cannot edit, so what goes out is never a surprise. */
.email-preview{max-width:var(--measure);margin:0 0 var(--space-3);padding:var(--space-3) var(--space-4);border:1px solid var(--line);background:var(--surface-inset)}
.email-preview p{margin:0 0 var(--space-2)}
.email-preview p:last-child{margin:0}
/* Same measure as the notice above it, so the two read as one column. */
.gate-help{max-width:var(--measure)}
.gate-notice{max-width:var(--measure);margin:0 0 var(--space-4);padding:var(--space-3) var(--space-4);border:1px solid var(--wax);background:var(--surface-inset);color:var(--text-body);font-size:var(--text-sm);line-height:1.6}
.gate-notice strong{color:var(--wax-bright)}
.gate-notice__ask{display:block;width:fit-content;margin-top:var(--space-3);font-size:var(--text-content)}
/* Requests waiting, on the admin pages' Invitations link. */
.nav-count{display:inline-block;min-width:1.4em;padding:0 .4em;border-radius:1em;background:var(--wax);color:var(--text-on-wax);font-size:var(--text-xs);font-weight:600;line-height:1.5;text-align:center;vertical-align:.1em}
/* The invitation form's honeypot: off screen, not display:none, so a bot that
   skips hidden fields still fills it. */
.honeypot{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.flash{padding:var(--space-3) var(--space-4);border:1px solid;border-radius:0;font-family:var(--font-mono);font-size:var(--text-sm);margin:var(--space-3) 0}
.flash--notice{background:var(--flash-notice-bg);border-color:var(--flash-notice-border);color:var(--moss)}
.flash--alert{background:var(--flash-alert-bg);border-color:var(--flash-alert-border);color:var(--error-text)}
.errors{background:var(--surface-inset);border:1px solid var(--ruby);border-radius:0;padding:var(--space-3) var(--space-4);margin-bottom:var(--space-4);color:var(--error-text);font-size:var(--text-sm)}
.errors ul{margin:0;padding-left:var(--space-4)}
/* Avatars: square, metal-set */
.avatar{border-radius:2px;object-fit:cover;border:1px solid var(--gold);background:var(--surface-inset)}
.avatar--card{width:36px;height:36px}
.avatar--profile{width:160px;height:160px;border-radius:4px}
.avatar--monogram{display:inline-flex;align-items:center;justify-content:center;color:var(--gold-bright);font-weight:600}
.avatar--monogram.avatar--card{font-size:.9rem}
.avatar--monogram.avatar--profile{font-size:3rem}
/* Profile page: the name is the title, the bio is prose, the facts are content */
.profile__actions{display:flex;align-items:center;gap:var(--space-4);margin-top:var(--space-5)}
.profile{margin-top:var(--space-6)}
.profile__bio{max-width:var(--measure)}
.profile__meta{font-size:var(--text-content);color:var(--text-muted);margin:0 0 var(--space-1)}
/* Rank */
.rank{font-family:var(--font-mono);font-weight:600;text-transform:lowercase;color:var(--gold-bright)}
.card__rank,.profile__rank{color:var(--text-muted);font-size:var(--text-xs)}
.card__rank .rank,.profile__rank .rank{font-size:1.1em}
/* Directory: one line per developer */
.directory{display:flex;gap:var(--space-6);align-items:flex-start;margin-top:var(--space-7)}
.directory__main{flex:1}

.directory__list{display:block}

/* The directory's filter bar. The search field overrides the global input
   width, which is a measure-wide block and pushed everything else onto a
   second line. Here it takes whatever is left instead. */
.filter-bar{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3);margin:0 0 var(--space-5)}
.filter-bar input[type="search"]{flex:1 1 14rem;width:auto;min-width:0;max-width:none}
/* The toggles are one thing, so they wrap as one and never split across lines. */
.filter-bar__toggles{display:flex;align-items:center;gap:var(--space-4);white-space:nowrap}
.filter-bar label{display:inline-flex;align-items:center;gap:var(--space-2);margin:0}
.filter-bar input[type="submit"]{flex:none}
@media (max-width:640px){.directory{flex-direction:column}
.site-header{flex-wrap:wrap;row-gap:var(--space-1)}
/* The nav carries more links than a phone is wide; without this it
   overflows sideways instead of wrapping. */
.site-header nav{flex-wrap:wrap;justify-content:flex-end;column-gap:var(--space-3);row-gap:var(--space-1)}
/* A row is one line wherever it fits. A long name may push the rank under it;
   it must never push the page sideways. */
.card{flex-wrap:wrap;row-gap:var(--space-1)}
.hero{padding:var(--space-5) var(--space-3)}}
/* One line per member, the way the Omarchy roster reads: name, rank, number.
   Location stays searchable and lives on the page and the globe, not here. */
.card{display:flex;align-items:center;gap:var(--space-3);width:100%;background:transparent;border:0;border-bottom:1px solid var(--line);border-radius:0;padding:var(--space-2);text-align:left}
.card:hover{background:var(--surface-inset)}
.card>a{display:flex;align-items:center;gap:var(--space-3);min-width:0;text-decoration:none;color:inherit}
.card h3{margin:0;font-size:1rem;min-width:0;overflow-wrap:anywhere}
.card>a:hover h3{color:var(--gold-bright)}
.card p{margin:0;font-size:var(--text-content);color:var(--text-muted)}
.card__rank{white-space:nowrap}
/* Sponsor plaque */
/* Badges: gems cut to the crest's shield. Glow sits on the seal span, the clip on its
   ::before, because a drop-shadow on the clipped element itself would be cut off. */
.badges{display:grid;grid-template-columns:repeat(auto-fill,minmax(14rem,1fr));gap:var(--space-3) var(--space-5);margin:0 0 var(--space-4);padding:0}
.badge{display:flex;align-items:center;gap:var(--space-3);list-style:none;margin:0;font-size:var(--text-content)}
.badge__seal{flex:none;filter:var(--seal-glow)}
.badge__seal::before{content:attr(data-seal);display:flex;align-items:center;justify-content:center;box-sizing:border-box;width:44px;height:51px;padding-bottom:6px;font-family:var(--font-mono);font-weight:600;font-size:1rem;color:rgba(255,255,255,.9);text-shadow:0 0 8px rgba(255,255,255,.4);background:linear-gradient(135deg,var(--wax-bright) 0%,var(--wax) 45%,var(--wax-dark) 100%);clip-path:var(--seal-shape)}
.badge--in-production .badge__seal{filter:var(--seal-rim) drop-shadow(0 0 6px rgba(0,0,0,.6)) drop-shadow(0 0 5px rgba(176,141,87,.3))}
.badge--in-production .badge__seal::before{background:linear-gradient(135deg,#c7a06a 0%,#8a6a3a 55%,#4a3a1e 100%);color:rgba(0,0,0,.65);text-shadow:0 1px 1px rgba(255,255,255,.35)}
.badge--founding-member .badge__seal{filter:var(--seal-rim) drop-shadow(0 0 6px rgba(0,0,0,.6)) drop-shadow(0 0 10px var(--glow))}
.badge--founding-member .badge__seal::before{background:linear-gradient(135deg,#fff 0%,var(--wax-bright) 25%,var(--wax) 55%,var(--wax-dark) 90%)}
/* Apps on a profile: name loud, description quiet, mark a small disc */
.apps__hint{font-size:var(--text-xs);margin:0 0 var(--space-3)}
.apps{list-style:none;margin:0 0 var(--space-4);padding:0}
.app{padding:var(--space-3) 0}
.app+.app{border-top:var(--rule-hairline)}
.app__name{display:flex;align-items:center;gap:var(--space-2);margin:0 0 var(--space-1)}
.app__description{font-size:var(--text-content);color:var(--text-muted);max-width:var(--measure);margin:0 0 var(--space-1)}
/* width:auto, never 100%: a member who uploads something small should see
   it small rather than blown up and blurry. The cap is the reading
   measure, or the screen on a phone, whichever is narrower.
   Height is capped too, or a square app icon fills 38rem of page the way a
   wide screenshot never does. 24rem is about what a 16:10 shot occupies at
   full measure, so the common case is untouched and only tall art is reined
   in; the aspect ratio holds either way. */
.app__source{font-size:var(--text-xs);font-family:var(--font-mono);margin:0 0 var(--space-2)}
.app__source a{color:var(--text-faint)}
.app__source a:hover{color:var(--link-hover)}
/* Only its owner sees a hidden app, and it should look like the exception it
   is without shouting: dimmed, with the reason and the way out on top. */
.app--hidden{opacity:.72}
.app__hidden{font-size:var(--text-xs);color:var(--gold-bright);margin:0 0 var(--space-1)}
.app__deployment{font-size:var(--text-xs);font-family:var(--font-mono);color:var(--text-faint);margin:0 0 var(--space-2)}
.app__stack{font-size:var(--text-xs);font-family:var(--font-mono);color:var(--text-faint);margin:0 0 var(--space-2)}
/* The app form's "How it's built" block. The Other box belongs to the select
   beside it and appears only when that select says Other. :has(), not
   Stimulus: this form has to work in the native apps and without JS like
   every other screen, the select is a native control that updates :checked
   as it is used, and with no CSS at all the box simply stays visible, which
   is the behaviour this replaced. */
.stack{border:1px solid var(--line);border-radius:var(--radius-md);padding:var(--space-3);margin:0 0 var(--space-3)}
.stack legend{font-size:var(--text-sm);padding:0 var(--space-1)}
.stack__note{font-size:var(--text-xs);color:var(--text-faint);margin:0 0 var(--space-3);max-width:var(--measure)}
.stack__choice{margin:0 0 var(--space-2)}
.stack__other{display:none}
/* Block, not inline-block: the box has to take the same left edge and the same
   width as the select it belongs to, and an inline-block shrinks to its
   content instead of honouring the width:100% those controls share. */
.stack__choice:has(option[value="other"]:checked) .stack__other{display:block;margin-top:var(--space-2)}
.app__screenshot{display:block;width:auto;max-width:min(var(--measure),100%);height:auto;max-height:24rem;border:1px solid var(--line);border-radius:var(--radius-md);margin:0 0 var(--space-2)}
/* On the edit form it is a thumbnail, not the main event. */
.app__screenshot--preview{max-width:min(16rem,100%)}
.app__actions{display:flex;align-items:center;gap:var(--space-2);font-size:var(--text-xs);margin:0}
.app__move{display:inline-flex;gap:var(--space-1)}
.app__move button{padding:0 var(--space-2);font-size:var(--text-sm);line-height:1.5;color:var(--text-faint);border-color:var(--line)}
.app__move button:hover:not(:disabled){background:transparent;border-color:var(--gold);color:var(--gold-bright)}
.app__move button:disabled{opacity:.3;cursor:default}
.app__actions a{color:var(--text-faint)}
.app__actions a:hover{color:var(--link-hover)}
.app__mark{flex:none;display:inline-flex;width:16px;height:16px;box-sizing:border-box;border-radius:50%;cursor:help}
.app__mark svg{display:block}
.app__mark--verified{color:var(--verified);filter:drop-shadow(0 0 4px var(--glow-moss))}
.app__mark--unverified{border:1px dashed var(--unverified)}
/* Token line */
.token-line{display:flex;align-items:stretch;gap:var(--space-2);max-width:var(--measure)}
.token-line code{flex:1;display:flex;align-items:center;padding:var(--space-2) var(--space-3);overflow-x:auto;white-space:nowrap;font-size:var(--text-sm)}
.token-line button{flex:none;font-size:var(--text-xs);padding:var(--space-2) var(--space-3)}
/* A button_to is a form, and a form has no bottom margin, so the back link
   was sitting on the button. The same gap a paragraph gets. */
.check-now{margin-bottom:var(--space-3)}
/* The badge embed on a member's own page. Folded by default: it is a tool,
   not part of the page's reading. */
.badge-embed{margin:0 0 var(--space-4);max-width:var(--measure)}
/* The summary is a button so it reads as an action beside Share, not as a
   footnote. list-item display would draw the disclosure marker over it. */
.badge-embed summary{display:inline-block;cursor:pointer;list-style:none}
.badge-embed summary::-webkit-details-marker{display:none}
.badge-embed[open] summary{margin-bottom:var(--space-3)}
.badge-embed__preview{display:block;margin:var(--space-3) 0}
.badge-embed__label{font-size:var(--text-xs);text-transform:lowercase;letter-spacing:.04em;color:var(--text-faint);margin:var(--space-3) 0 var(--space-1)}
/* The agent hand-off, framed so it reads as the way in rather than as one
   option among three. Gold rule plus a soft glow, the same pair the seals use. */
.agent-handoff{max-width:var(--measure);margin:var(--space-5) 0;padding:var(--space-4);border:1px solid var(--wax);box-shadow:0 0 12px var(--glow-soft)}
.agent-handoff h2{margin-top:0}
.agent-handoff__flag{display:inline-block;margin:0 0 var(--space-3);padding:.15em .6em;font-family:var(--font-mono);font-weight:600;font-size:var(--text-xs);letter-spacing:.06em;text-transform:lowercase;color:var(--text-on-wax);background:var(--wax)}
.agent-handoff .agent-prompt{margin-bottom:0}
.agent-prompt{max-width:var(--measure);margin-bottom:var(--space-5)}
.agent-prompt pre{margin:0 0 var(--space-2);padding:var(--space-3) var(--space-4);font-family:var(--font-mono);font-size:var(--text-xs);line-height:1.5;color:var(--text-muted);background:var(--surface-inset);border:var(--rule-hairline);white-space:pre-wrap;overflow-wrap:anywhere;max-height:16rem;overflow-y:auto}
.agent-prompt button{font-size:var(--text-xs);padding:var(--space-2) var(--space-3)}
/* Sponsor rails: TrustMRR-style flanking inventory, guild-dressed */
.rails{display:grid;grid-template-columns:15rem minmax(0,1fr) 15rem;gap:var(--space-6);align-items:start;max-width:96rem;margin:0 auto;padding:0 var(--space-5)}
.rails>.page{max-width:var(--page-max);padding:0;min-width:0}
/* Grid, not flex: the label keeps its own auto row and every plaque below
   it shares one row height. Content stays top-aligned so logos and names
   line up across plaques. */
.sponsor-rail{display:grid;grid-template-rows:auto;grid-auto-rows:1fr;gap:var(--space-4);position:sticky;top:var(--space-5);padding-top:var(--space-5)}
.sponsor-rail__label{font-size:var(--text-xs);letter-spacing:.04em;text-transform:lowercase;color:var(--gold);margin:0}
.sponsor{border:1px solid var(--line);padding:var(--space-3);text-align:center;min-height:9rem}
.sponsor:hover{border-color:var(--gold)}
.sponsor__logo{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border:1px solid var(--gold);border-radius:2px;color:var(--gold-bright);font-weight:600;margin-bottom:var(--space-2)}
.sponsor__logo img{width:100%;height:100%;object-fit:contain}
.sponsor a{display:block;font-weight:600;color:var(--text-body);text-decoration:none}
.sponsor a:hover{color:var(--gold-bright)}
.sponsor p{margin:var(--space-1) 0 0;font-size:var(--text-content);color:var(--text-muted)}
.sponsor--empty{border-style:dashed}
.sponsor--empty:hover{border-color:var(--gold)}
.sponsor--empty .sponsor__logo{border-style:dashed;color:var(--text-faint)}
.sponsor--empty a{font-weight:400;font-style:italic;color:var(--text-muted);text-decoration:underline;text-decoration-color:var(--line)}
.sponsor--empty a:hover{color:var(--gold-bright)}
.sponsor--empty p{color:var(--text-faint)}
@media (max-width:1100px){
.rails{display:flex;flex-direction:column;padding:0 var(--space-5) 5.5rem}
.rails>.page{order:1}
.sponsor-rail{display:flex;position:static;flex-direction:row;flex-wrap:nowrap;overflow-x:auto;align-items:center;gap:var(--space-3);padding:var(--space-3) 0;scrollbar-width:thin}
.sponsor-rail__label{display:none}
.sponsor-rail--left{order:0;border-bottom:var(--rule-hairline)}
.sponsor-rail--right{position:fixed;top:auto;left:0;right:0;bottom:0;z-index:10;background:var(--parchment);border-top:1px solid var(--gold);padding:var(--space-2) var(--space-3);margin:0}
.sponsor-rail .sponsor{flex:0 0 auto;display:flex;align-items:center;gap:var(--space-2);padding:var(--space-2) var(--space-3);text-align:left;min-height:0}
.sponsor-rail .sponsor__logo{width:24px;height:24px;margin:0;font-size:.7rem;flex:none}
.sponsor-rail .sponsor a{font-size:var(--text-sm);white-space:nowrap}
.sponsor-rail .sponsor p{display:none}
}
/* Globe */
/* Globe: a canvas beside the same roster in words. The list is the fallback,
   so it stays readable on its own and the canvas only ever selects into it. */
.globe{display:flex;gap:var(--space-6);align-items:flex-start;margin:var(--space-5) 0}
.globe__canvas{flex:none;width:min(30rem,52vw);aspect-ratio:1;touch-action:none;cursor:grab}
/* Empty until the browser has something to say, so it takes no room when silent. */
.globe-picker__status:empty{display:none}
.globe-picker__status{font-size:var(--text-xs);margin:0 0 var(--space-3)}
.globe__canvas:active{cursor:grabbing}
.globe__canvas:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}
.globe__roster{flex:1;min-width:0;list-style:none;margin:0;padding:0;max-height:min(30rem,52vw);overflow-y:auto}
.globe__entry{padding:var(--space-2) var(--space-3);border-bottom:1px solid var(--line);font-size:var(--text-content);cursor:default}
.globe__entry:focus-visible{outline:2px solid var(--focus-ring);outline-offset:-2px}
.globe__entry.is-selected{background:var(--surface-inset);border-left:2px solid var(--globe-dot)}
.globe__handle,.globe__place{color:var(--text-muted);font-size:var(--text-xs);margin-left:var(--space-2)}
.globe__anonymous{color:var(--text-faint);font-style:italic}
.globe__entry--empty{color:var(--text-faint)}
.globe__cta{font-size:var(--text-sm)}
/* The picker on the profile form: the same globe, one dot, and fields that can
   do the job on their own for anyone not using a pointer. */
.globe-picker{border:1px solid var(--line);border-radius:0;padding:var(--space-4);margin:var(--space-5) 0;max-width:var(--measure)}
.globe-picker legend{font-size:var(--text-sm);color:var(--gold-bright);padding:0 var(--space-2)}
.globe-picker p{font-size:var(--text-sm)}
.globe-picker .globe__canvas{width:min(22rem,70vw);margin:var(--space-3) 0}
.globe-picker__readout{display:flex;align-items:center;gap:var(--space-3);flex-wrap:wrap}
.globe-picker__readout span{font-family:var(--font-mono);color:var(--gold-bright)}
.globe-picker__fields{display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap}
.globe-picker__fields input{width:7rem}
@media (max-width:720px){.globe{flex-direction:column}
.globe__canvas{width:min(30rem,86vw)}}

/* Patron dialog: the plaque pitch, opened from any "become a patron" link */
/* The pitch made it taller than a phone, so the dialog scrolls rather than
   running its CTA off the bottom of the screen. */
.patron-dialog{max-width:34rem;width:calc(100% - 2*var(--space-5));max-height:calc(100dvh - 2*var(--space-5));overflow-y:auto;background:var(--surface-card);color:var(--text-body);border:1px solid var(--gold);padding:var(--space-6);margin:auto}
.patron-dialog::backdrop{background:rgba(0,0,0,.6)}
.patron-dialog h2{margin-top:0}
.patron-dialog h3{margin-bottom:var(--space-2)}
.patron-dialog__lede{color:var(--text-muted)}
.patron-dialog__close{position:absolute;top:var(--space-3);right:var(--space-3);border:0;padding:var(--space-1) var(--space-2);font-size:1.1rem;line-height:1;color:var(--text-muted)}
.patron-dialog__close:hover{background:transparent;color:var(--gold-bright)}
.patron-dialog__stats{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--space-3);margin:var(--space-4) 0}
.patron-dialog__stats>div{border:1px solid var(--line);padding:var(--space-3);text-align:center}
.patron-dialog__stats strong{display:block;color:var(--gold-bright)}
.patron-dialog__stats span{font-size:var(--text-xs);color:var(--text-muted)}
.patron-dialog__stat--scarce{border-color:var(--gold)}
.patron-dialog__pricing{background:var(--surface-inset);border:1px solid var(--line);padding:var(--space-3) var(--space-4);margin:var(--space-4) 0}
.patron-dialog__pricing p{margin:var(--space-1) 0}
.patron-dialog__cta{width:100%;text-align:center}

/* Masthead: the crest above the directory for signed-in members */
.masthead{text-align:center;padding:var(--space-6) 0 0}
.masthead__mark{height:96px;width:auto}
.masthead__ledger{font-size:var(--text-content);color:var(--text-muted);margin:var(--space-3) 0 0}

/* ===== ledger tables ===== */
/* Every table in the app is an admin ledger, so these are bare element rules:
   the mailer layout carries its own styles and never loads this file. The
   look is the ledger it is named for. A gold rule under the headings, hairline
   rules between the entries, and enough air that two dates in neighbouring
   columns read as two dates rather than one number. */
.ledger{overflow-x:auto;margin:0 0 var(--space-5)}
table{width:100%;border-collapse:collapse;font-size:var(--text-sm)}
/* Headings are chrome: small caps in faint ink, so the entries are what the
   eye lands on. nowrap because a wrapped heading doubles the header's height
   for no gain. */
th{text-align:left;font-weight:600;font-size:var(--text-xs);text-transform:uppercase;letter-spacing:var(--tracking-caps);color:var(--text-faint);white-space:nowrap;border-bottom:var(--rule-major);padding:0 var(--space-4) var(--space-2) 0}
td{padding:var(--space-3) var(--space-4) var(--space-3) 0;border-bottom:var(--rule-hairline);vertical-align:middle}
/* No left padding anywhere, so the first column lines up with the prose above
   it; the gap between columns is the previous one's right padding. */
th:last-child,td:last-child{padding-right:0;text-align:right}
tbody tr:hover{background:var(--surface-inset)}
tbody tr:last-child td{border-bottom:0}
/* A button_to is a form, and a block form inside a cell sets the row's height.
   Inline, small, and the rows stay even whether or not they carry an action. */
td form{display:inline;margin:0}
td button,td input[type="submit"]{font-size:var(--text-xs);padding:var(--space-1) var(--space-3)}
td code{white-space:nowrap}
td time,td .ledger__date{white-space:nowrap}
/* Figures line up under each other and read as a column of figures. */
.ledger__num{text-align:right;font-variant-numeric:tabular-nums}
.ledger__empty{color:var(--text-faint)}
/* An invite request's message, folded under its subject until asked for. */
.invite-request__excerpt{white-space:normal;max-width:var(--measure);margin:var(--space-2) 0 0;font-size:var(--text-sm)}
.pager{display:flex;gap:var(--space-4);margin:0 0 var(--space-5)}
