@font-face{
  font-family:"Source Serif Pro";
  src:url("/assets/fonts/source-serif-400-latin.woff2") format("woff2");
  font-weight:400;font-style:normal;font-display:swap;
}
:root{
  color-scheme:light dark;
  --paper:#f1f2f0; --surface:#fdfdfc; --panel:#e4e6e3;
  --ink:#101211;   --muted:#5a5f5c;   --line:#d3d6d3; --line-strong:#b3b8b4;
  --accent:#b0431f; --accent-hover:#93351a; --accent-ink:#fdfdfc;
  --status-bg:#ece7d8; --status-ink:#6a5514; --status-accent:#a98a2c;
  --alert-bg:#f0e2dd;  --alert-ink:#8a2b1c; --alert-accent:#b0553f;
  --ok-bg:#e2e8dd;     --ok-ink:#3f5232;
  --radius:0; --shadow:none;
  --serif:"Source Serif Pro",Georgia,"Times New Roman",serif;
  --sans:system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
}
@media (prefers-color-scheme:dark){:root{
  --paper:#151716; --surface:#1d201e; --panel:#262a28;
  --ink:#eaedeb;   --muted:#99a19c;   --line:#313634; --line-strong:#4a524e;
  --accent:#e58058; --accent-hover:#ef946f; --accent-ink:#211009;
  --status-bg:#2a2717; --status-ink:#ddc98a; --status-accent:#8d7b30;
  --alert-bg:#2e1a14;  --alert-ink:#eda78c; --alert-accent:#a55a41;
  --ok-bg:#212a20;     --ok-ink:#b5c8ab;
}}
*{box-sizing:border-box;border-radius:0}
html{background:var(--paper)}
body{max-width:34rem;margin:0 auto;padding:1.75rem 1.25rem 3.5rem;background:var(--paper);
  color:var(--ink);font:400 1rem/1.6 var(--sans);-webkit-text-size-adjust:100%}
body.console,.console{max-width:52rem}
/* The masthead rule is FULL-BLEED (owner decision, 2026-07-29; design spec §04
   draws it and the reservation slip running to the edge). The rule is painted
   by this border, so bleeding it means bleeding main itself: negative side
   margins cancel the body's gutter, and equal padding puts the content back
   where it was. Nothing inside main moves.
   "Edge" means the BODY's edge, not the viewport's -- body is max-width'd and
   centred, so on a phone this is the screen and on a desktop it is the measure.
   A rule spanning a 1920px window was never what the mock showed.
   This is deliberately on main, so it applies to every screen. Bleeding the
   slip alone leaves this rule 1.25rem short at each shoulder, which reads as a
   broken rule rather than an inset one -- that option was rejected on sight. */
main{border-top:5px solid var(--ink);padding-top:1.5rem;
  margin-left:-1.25rem;margin-right:-1.25rem;padding-left:1.25rem;padding-right:1.25rem}
.confirmed-page main{border-top-color:var(--accent)}
h1{font:600 clamp(2rem,8vw,2.5rem)/1.03 var(--sans);letter-spacing:-.03em;
  text-transform:uppercase;text-wrap:balance;margin:.1em 0 .75rem}
h2{font:600 1.35rem/1.1 var(--sans);letter-spacing:-.01em;text-transform:uppercase;margin:1.7rem 0 .65rem}
label>span,legend,dt,h3,h4,.badge,.steps,.crumbs,nav.foot a,.micro,.eyebrow{
  font:700 .625rem/1 var(--sans);letter-spacing:.18em;text-transform:uppercase;color:var(--muted)}
h3,h4{margin:1.4rem 0 .6rem}
p{margin:0 0 1rem}
.voice{font:400 1.05rem/1.6 var(--serif)}
.welcome.voice{color:var(--muted)}
a{color:var(--accent);text-underline-offset:2px}
a:hover{color:var(--accent-hover)}
a:active{color:var(--accent-hover)}
a:focus-visible,button:focus-visible,summary:focus-visible,input:focus-visible,
textarea:focus-visible,select:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
strong{font-weight:700}
time,.url,.count,.mono,input[type=datetime-local],input.code{font-family:var(--mono)}
hr{border:0;border-top:1px solid var(--line);margin:2rem 0}
section{margin:1.5rem 0}
ul{margin:.5rem 0 1.1rem;padding-left:1.2rem}
li{margin:.35rem 0}
/* Full-bleed, per design spec §02 ("Optional cover image: full-bleed above the
   eyebrow"). It was the last element still stopping at the text margin after the
   masthead rule and the slip moved to the edge, which made it read as a framed
   picture pasted onto the page rather than the top of the page.
   The WIDTH is stated, not left auto: an <img> is replaced content, so width:auto
   means its INTRINSIC width (1200px here) and blows the layout apart rather than
   filling the box. Measured, not assumed. The 1.25rem is the body gutter that
   main cancels and restores -- the fourth place that number appears. */
/* Safety net for replaced content: an <img> with no explicit width (the club
   settings upload previews) otherwise renders at its intrinsic pixel width and
   blows the page wide, as the comment above describes. Clamp any such image to
   its container. The full-bleed cover/banner set max-width:none and the avatar
   sets a fixed width, so all of them win on specificity and are unaffected. */
img{max-width:100%;height:auto}
img.cover{display:block;height:auto;border-radius:0;box-shadow:none;
  margin:0 -1.25rem 1.5rem;width:calc(100% + 2.5rem);max-width:none}
/* The eyebrow shares the label family's font shorthand, which sets line-height
   to 1. That was fine while it read "Thu 08 Aug" and could not wrap; naming the
   Club in front of the date (spec §02) makes wrapping reachable at 390px, and at
   line-height 1 the two lines collide -- the same defect apps/web/AGENTS.md
   records for .micro prose. 1.7 matches .when .venue, the other tracked-
   uppercase line in this stylesheet that is expected to wrap. */
.eyebrow{color:var(--accent);letter-spacing:.26em;line-height:1.7}
[role=status],[role=alert]{padding:.8rem 1rem;margin:0 0 1.35rem;border:1px solid;
  font-size:.96rem;line-height:1.45;border-radius:0;box-shadow:none}
[role=status]{background:var(--status-bg);color:var(--status-ink);border-color:var(--status-accent)}
[role=alert]{background:var(--alert-bg);color:var(--alert-ink);border-color:var(--alert-accent)}

/* Shared date block: compact is the dashboard's date rail. */
.when{display:grid;grid-template-columns:auto 1fr;gap:0 1.1rem;align-items:center;
  border-top:2px solid var(--ink);border-bottom:1px solid var(--ink);padding:.8rem 0;margin:1.4rem 0}
.when .cal{text-align:center;line-height:1;min-width:3.25rem}
.when .dow,.when .mon{font:700 .625rem/1 var(--sans);letter-spacing:.18em;
  text-transform:uppercase;color:var(--muted)}
.when .day{display:block;font:600 2.6rem/.95 var(--sans);letter-spacing:-.04em;margin:.3rem 0}
.when .detail{border-left:1px solid var(--line);padding-left:1.1rem}
.when .hours{font:600 1.05rem/1 var(--mono)}
.when .venue{font:600 .69rem/1.7 var(--sans);letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted);margin:.45rem 0 0}
.when.compact{display:block;border:0;margin:0;padding:0}
.when.compact .cal{display:block;min-width:3.25rem}
.when.compact .day{font-size:1.6rem}

/* Forms: console fields are boxed; the invitation form overrides them below. */
form{margin:1.5rem 0}
label{display:block;margin:0 0 1.1rem;font-weight:600;font-size:.95rem}
/* Enumerating input types means every new type is opted OUT by default and
   silently renders as an inline browser default. type=number (the Seats field,
   0024) sat outside this list and rendered 147px wide, inline with its label,
   in a grid where every sibling is a full-width block; type=file had already
   hit the same gap and been patched separately below. Adding a type here is the
   checklist item whenever a console field uses a new one. */
input[type=text],input[type=email],input[type=password],input[type=search],
input[type=number],input[type=tel],input[type=url],
input[type=datetime-local],textarea,select{display:block;width:100%;margin-top:.4rem;
  font:inherit;font-size:1rem;color:var(--ink);background:var(--surface);
  border:1px solid var(--line-strong);padding:.72rem .85rem;border-radius:0;box-shadow:none}
textarea{min-height:5rem;resize:vertical}
input:focus,textarea:focus,select:focus{border-color:var(--accent)}
input[type=checkbox],input[type=radio]{accent-color:var(--accent);width:1.05em;height:1.05em;
  vertical-align:-2px;margin-right:.45rem}
fieldset{border:1px solid var(--line);padding:1rem 1.1rem;margin:0 0 1.1rem}
legend{padding:0 .4rem}
button,a.btn{display:inline-block;min-height:2.75rem;cursor:pointer;background:var(--ink);color:var(--paper);
  border:1px solid var(--ink);padding:.78rem 1.3rem;text-decoration:none;font:700 .8rem/1 var(--sans);
  letter-spacing:.14em;text-transform:uppercase;transition:background .15s ease}
button:hover,a.btn:hover{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
button:active,a.btn:active{background:var(--accent-hover);border-color:var(--accent-hover);color:var(--accent-ink)}
button.secondary,.btn.secondary{background:transparent;color:var(--ink);border-color:var(--ink)}
button.secondary:hover,.btn.secondary:hover{background:var(--surface);color:var(--accent)}
form button[type=submit]{width:100%;margin-top:.35rem}

/* 01 — invitation landing. */
.hero{text-align:left;padding:1rem 0 .5rem}
.hero h1{border-bottom:1px solid var(--ink);padding-bottom:1rem}
.hero .tagline{font:700 .625rem/1.5 var(--sans);letter-spacing:.18em;text-transform:uppercase;color:var(--muted)}
/* Landing layout B: a profile header with a full-width banner and a Club mark
   crossing its lower edge. The mark keeps the sheet's SQUARE corners (the
   universal zero-radius reset is a tested design-pass invariant); the
   paper frame keeps transparent logos legible over both light and dark covers
   without flattening their alpha channel. */
.profile-header{text-align:center;padding-top:0}
.profile-header .banner{display:block;width:calc(100% + 2.5rem);max-width:none;height:auto;
  margin:0 -1.25rem 0;aspect-ratio:16/7;object-fit:cover}
.profile-header .avatar{display:block;width:7rem;height:7rem;object-fit:contain;
  margin:1.25rem auto;border:4px solid var(--paper);
  background:transparent;box-shadow:0 0 0 1px var(--line-strong)}
.profile-header .banner+.avatar{margin-top:-3.5rem;position:relative}
.profile-header .banner+.eyebrow{margin-top:1.5rem}
/* Keep the .eyebrow leading here too: this is the LAST .eyebrow rule in the
   sheet, and a wrapped eyebrow depends on the 1.7 leading (public-event-page
   pins that the last rule restates it, since the .eyebrow font shorthand sets
   line-height:1). */
.profile-header .eyebrow{margin-bottom:.65rem;line-height:1.7}
.profile-header h1{margin-left:auto;margin-right:auto}
.invite-card{background:var(--panel);border:1px solid var(--line-strong);
  padding:1.5rem 1.35rem;box-shadow:none}
.invite-card h2{font-size:.625rem;letter-spacing:.18em;margin-top:0;color:var(--accent)}
/* The explainer's fallback line ("Can't find it? Check spam…") is secondary to
   the sentence above it, and the §01 mock draws it muted. The markup has always
   carried this class; the rule was simply missing, so it rendered identical to
   the copy it is meant to sit under. */
.invite-card .note{color:var(--muted)}
.invite-card p:last-child{margin-bottom:0}
nav.foot{display:flex;gap:1rem;align-items:center;margin-top:2.5rem;padding-top:1.1rem;
  border-top:1px solid var(--ink)}
nav.foot a{display:inline-flex;align-items:center;min-height:2.75rem;color:var(--muted)}
nav.foot a.organizer{margin-left:auto;color:var(--accent)}

/* 02 — event invitation and RSVP. */
form.rsvp{background:transparent;border:0;border-top:2px solid var(--ink);
  padding:1.3rem 0 0;box-shadow:none}
form.rsvp h2{margin-top:0}
.rsvp input[type=text],.rsvp input[type=email]{background:transparent;border:0;
  border-bottom:1px solid var(--ink);padding:.55rem .1rem;font-size:1rem}
.rsvp input:focus{border-bottom-width:2px;border-color:var(--accent);outline:none}
.rsvp input:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
.rsvp details.companions{margin:1.2rem 0}
.rsvp details.companions summary{display:flex;min-height:2.75rem;align-items:center;justify-content:space-between;
  list-style:none;background:var(--panel);padding:.9rem;
  font:700 .625rem/1 var(--sans);letter-spacing:.18em;text-transform:uppercase;cursor:pointer}
.rsvp details.companions summary::-webkit-details-marker{display:none}
.rsvp details.companions summary::after{content:"＋";color:var(--accent);font-size:1rem}
.rsvp details.companions[open] summary::after{content:"−"}
.rsvp details.companions fieldset{display:contents}
/* The <summary> above already labels this group, and spec §02 keeps the
   <fieldset> only "for semantics". While the guest labels rendered as body copy
   the legend read as their heading; now that they carry the house style it is a
   third stacked micro-label saying the same thing. Hidden VISUALLY only -- it
   still reaches assistive tech, which is the whole reason the fieldset exists. */
.rsvp details.companions legend{position:absolute;width:1px;height:1px;margin:-1px;
  padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
.rsvp .companions input,.rsvp .host-questions input{border-bottom-color:var(--line-strong)}
.host-questions{border:0;border-top:2px solid var(--accent);padding:.9rem 0 .2rem}
.host-questions legend{color:var(--accent);padding:0;margin-bottom:1rem}
.host-questions label{font-size:.875rem;font-weight:600}
.rsvp button[type=submit]{padding:1rem 1.5rem}
.rsvp .helper{text-align:center;font:700 .625rem/1.4 var(--sans);letter-spacing:.14em;
  text-transform:uppercase;color:var(--muted);margin-top:.75rem}

/* 03 — verification. */
.steps{display:flex;align-items:center;gap:.4rem;margin:0 0 1rem}
.steps .bar{display:block;width:1.625rem;height:.25rem;background:var(--line)}
.steps .bar.done{background:var(--line-strong)}
.steps .bar.current{background:var(--accent)}
.steps .label{margin-left:.35rem}
.code-entry input.code,.hero-code{font:600 2.25rem/1 var(--mono);letter-spacing:.3em;
  text-align:center;background:var(--surface);border:1px solid var(--ink);padding:1.1rem .4rem}
.code-actions{display:flex;justify-content:space-between;align-items:center;border-top:1px solid var(--line);
  margin-top:2.5rem;padding-top:1rem}
.code-actions form{margin:0}
.code-actions button{width:auto!important;background:transparent;border:0;color:var(--accent);
  padding:0;font-size:.625rem}
.code-actions a{display:inline-flex;min-height:2.75rem;align-items:center;color:var(--muted);
  font:700 .625rem/1 var(--sans);letter-spacing:.18em;
  text-transform:uppercase}

/* 04 — confirmed/manage. The slip hangs flush under the masthead rule and runs
   to the same edge (owner decision, 2026-07-29): the negative TOP margin cancels
   main's padding-top so the two meet with no seam, and the negative SIDE margins
   cancel the padding main now uses to hold its content in place. Both numbers
   are tied to the body gutter above — change one, change all three. */
.slip{border-left:0;margin:-1.5rem -1.25rem 1.5rem;padding:.8rem 1rem;text-align:center;
  font:700 .69rem/1 var(--sans);letter-spacing:.2em;text-transform:uppercase}
.confirmed-bar{background:var(--accent);color:var(--accent-ink)}
/* Queued, not seated: the status pair, never accent — accent is reserved for a
   guest who actually holds a chair. */
.waitlist-bar{background:var(--status-bg);color:var(--status-ink)}
.event-line{font:400 1.05rem/1.4 var(--sans);color:var(--muted);margin:0 0 1.35rem}
.when a.micro{display:inline-flex;min-height:2.75rem;align-items:center;color:var(--accent);text-decoration:none}
.when a.micro:hover{color:var(--accent-hover);text-decoration:underline}
.party-list,.events-table,.roster-table{list-style:none;padding:0;margin:1rem 0}
.party-list>li{display:flex;justify-content:space-between;align-items:baseline;gap:1rem;
  padding:.9rem 0;border-bottom:1px solid var(--line);font-weight:600}
.party-list .role{font:700 .625rem/1 var(--sans);letter-spacing:.18em;text-transform:uppercase;color:var(--muted)}
.event-list,.club-list{list-style:none;margin:0;padding:0}
.event-list>li,.club-list>li{border-top:1px solid var(--line);padding:.9rem 0}
.event-list>li:first-child,.club-list>li:first-child{border-top:0}
.club-list>li{display:flex;gap:1rem;align-items:baseline;justify-content:space-between;flex-wrap:wrap}
.club-list>li>span{font:400 1rem/1.4 var(--sans)}
.me-event{display:grid;grid-template-columns:auto 1fr;gap:0 1.1rem;align-items:start}
.me-event .body{min-width:0}
.leave-club{background:transparent;border:0;color:var(--muted);font:700 .625rem/1 var(--sans);letter-spacing:.14em;text-transform:uppercase;cursor:pointer;padding:.3rem 0}
.leave-club:hover{color:var(--accent)}
/* "Change your response" is a major section boundary, so it opens on a 2px ink
   rule like every other one in the system. */
.response-form{border-top:2px solid var(--ink);margin-top:1.7rem;padding-top:1.2rem}
/* legend's default .4rem side padding indented this label out of alignment with
   the control underneath it; a bare fieldset has no border to clear. */
fieldset.bare>legend{padding:0}
.seg{display:flex;margin-top:.6rem}
.seg input{position:absolute;opacity:0;pointer-events:none}
.seg label{display:flex;min-height:2.75rem;flex:1;align-items:center;justify-content:center;text-align:center;
  border:1px solid var(--line-strong);border-left:0;
  padding:.75rem .25rem;margin:0;font:700 .69rem/1 var(--sans);letter-spacing:.12em;
  text-transform:uppercase;cursor:pointer}
.seg label:first-of-type{border-left:1px solid var(--line-strong)}
.seg input:checked+label{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
.seg input:focus-visible+label{outline:2px solid var(--accent);outline-offset:2px}
/* Selector must out-specify form button[type=submit] (0,1,2), which otherwise
   wins on width and margin and stretches this link into a full-width strip
   pinned under the Save button. Spec §04: a centered muted micro-link, never a
   button. */
form button[type=submit].cancel-rsvp{display:block;width:auto;margin:1.6rem auto 0;padding:.4rem;
  background:transparent;border:0;text-align:center;color:var(--muted);font:700 .625rem/1 var(--sans);
  letter-spacing:.18em;text-transform:uppercase;text-decoration:underline;text-underline-offset:3px}
.cancel-rsvp:hover{background:transparent;color:var(--alert-ink)}
fieldset.bare{border:0;padding:0}

/* Console masthead and dashboard. The title/action row is independent of headers. */
.masthead{display:flex;flex-wrap:wrap;align-items:baseline;gap:.35rem .75rem;margin:0 0 .4rem;
  padding-bottom:.9rem;border-bottom:1px solid var(--ink)}
.masthead .site{display:inline-flex;align-items:center;min-height:2.75rem;font:600 .95rem/1 var(--sans);letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink);text-decoration:none}
.masthead .role{background:var(--ink);color:var(--paper);padding:.28rem .5rem;
  font:700 .625rem/1 var(--sans);letter-spacing:.18em;text-transform:uppercase}
.masthead .who{margin-left:auto;font:400 .75rem/1 var(--mono);color:var(--muted)}
.crumbs{margin:1rem 0 1.4rem}
.crumbs a{display:inline-flex;align-items:center;min-height:2.75rem;color:var(--muted)}
/* console.js appends its paste/drop hint and status as .micro spans here. Both
   are inline by default, so they landed alongside the file input and collided
   with it; the whole field stacks instead. */
.cover-field input[type=file]{display:block;width:100%;margin-top:.4rem}
.cover-field .micro{display:block;margin-top:.35rem;text-transform:none;letter-spacing:normal}
.title-actions{display:flex;align-items:baseline;justify-content:space-between;gap:1rem;
  margin:1.5rem 0 1rem}
.title-actions h1{margin:0}
.table-head{clear:both;margin-top:0}
.badge,.state{display:inline-block;padding:.3rem .5rem;vertical-align:.2em}
.badge.published{background:var(--accent);color:var(--accent-ink)}
.badge.draft{border:1px dashed var(--line-strong);color:var(--muted);background:transparent}
.badge.canceled{background:var(--alert-bg);color:var(--alert-ink)}
/* The last column was 9.5rem, sized by the spec for "9 GO · 1 MB · 12 PAX".
   The jargon sweep replaced that with "9 going · 1 maybe · 12 guests", which
   wrapped mid-phrase at DESKTOP width, stranding "12 guests" on its own line.
   max-content gives it one line whenever there is room. The minmax() floors are
   load-bearing: an earlier cut used min-content plus nowrap, which cannot
   shrink, so the worst-case string this renderer can build ("... 3 waitlisted
   FULL, over capacity by 5") took 533px, collapsed the title track to ZERO and
   overflowed the page by 124px at 641px -- measured, between this grid and the
   640px stacking breakpoint below. The count must be allowed to wrap when the
   viewport genuinely cannot hold it. */
.events-table .table-head,.events-table .event-row{display:grid;
  grid-template-columns:3.75rem minmax(8rem,1fr) 6.5rem minmax(0,max-content);
  gap:1rem;align-items:center}
.events-table .table-head{padding:.55rem 0;border-bottom:1px solid var(--ink)}
.events-table .event-row{padding:.9rem 0;border-bottom:1px solid var(--line);
  color:var(--ink);text-decoration:none}
.events-table .event-row:hover,.roster-table .roster-row:hover{background:var(--surface)}
.events-table .event-title{font:600 1.1rem/1.15 var(--sans);text-transform:uppercase}
.events-table .meta{display:block;font:700 .625rem/1.5 var(--sans);letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted)}
/* Deliberately NOT nowrap: see the grid note above. Wrapping is the pressure
   valve that keeps a long count from overflowing the page. */
.events-table .count{text-align:right;font-size:.75rem}
.events-table .draft-row{color:var(--muted)}
/* Existing card hooks stay square until later renderers move to table markup. */
.event-cards,.events{list-style:none;padding:0}
.event-cards>li,.events>li{border-bottom:1px solid var(--line);padding:.9rem 0}
.event-cards a.card{display:block;color:var(--ink);text-decoration:none}
.card-top{display:flex;justify-content:space-between;gap:.75rem}
.card .meta,.org,.summary{color:var(--muted)}

/* 06 — organizer event header band and edit form. */
.event-heading{display:flex;align-items:baseline;gap:1rem}
.header-band{display:grid;grid-template-columns:1fr 1fr;border-top:2px solid var(--ink);
  border-bottom:1px solid var(--ink);margin:1.4rem 0}
.header-band>section{margin:0;padding:1.25rem}
.header-band>section+section{border-left:1px solid var(--line)}
.guest-link{background:var(--panel)}
.guest-link .url,.share .url{display:block;font:400 .9rem/1.5 var(--mono);word-break:break-all;
  user-select:all}
.covers{display:flex;gap:1.25rem}
.covers strong{display:block;font:600 1.9rem/1 var(--mono)}
.share{background:var(--panel);border:0;border-top:2px solid var(--ink);
  border-bottom:1px solid var(--ink);padding:1rem 1.15rem}
.edit-heading{display:flex;align-items:end;justify-content:space-between;gap:1rem;
  border-bottom:1px solid var(--ink)}
.edit-heading .warning{color:var(--alert-ink);text-align:right}
.field-grid{display:grid;grid-template-columns:1fr 1fr;gap:0 1rem}
.edit-form .actions{text-align:right}
.edit-form .actions button{width:auto}
details.danger{border-top:1px solid var(--line);padding-top:1rem;margin-top:2.5rem}
details.danger summary{display:flex;min-height:2.75rem;align-items:center;color:var(--alert-ink);
  cursor:pointer;font:700 .625rem/1 var(--sans);
  letter-spacing:.18em;text-transform:uppercase}
details.danger summary::after{content:"＋";margin-left:auto;color:var(--alert-ink);font-size:1rem}
details.danger[open] summary::after{content:"−"}
.danger button{background:var(--alert-accent);border-color:var(--alert-accent);color:var(--accent-ink)}

/* 07 — create-page label rail. */
.label-rail{display:grid;grid-template-columns:10rem 1fr}
.label-rail fieldset{display:contents}
.label-rail .rail-label,.label-rail .rail-fields{padding:1.25rem 0;border-bottom:1px solid var(--line)}
.label-rail .rail-label{padding-right:1.25rem}
.label-rail .rail-fields{padding-left:1.25rem}
.label-rail .rail-label:first-of-type,.label-rail .rail-label:first-of-type+.rail-fields{
  border-top:2px solid var(--ink)}
.label-rail .guidance{margin:.55rem 0 0}
/* Helper PROSE, as opposed to .micro, which is a tracked-uppercase LABEL set at
   line-height 1. A sentence in that style crams its lines together and is
   genuinely hard to read -- reported from a phone, 2026-07-28. Anything longer
   than a couple of words belongs here instead. */
.guidance{font-size:.85rem;line-height:1.45;letter-spacing:normal;text-transform:none;
  font-weight:400;color:var(--muted);margin:.6rem 0 1rem}
.guidance strong{font-weight:700;color:var(--ink)}
.label-rail .add-slot{border:1px dashed var(--line-strong);background:transparent}
.create-actions{display:flex;align-items:center;justify-content:space-between;gap:1rem;
  border-top:2px solid var(--ink);padding-top:1rem}
.create-actions .buttons{display:flex;align-items:center;gap:1rem}
.create-actions .discard{display:inline-flex;align-items:center;min-height:2.75rem;padding:0 .25rem;color:var(--muted)}
.question-slot .check-label{display:flex;align-items:center;min-height:2.75rem}

/* 08 — roster. */
.roster-summary{font:400 .78rem/1.5 var(--mono);color:var(--muted)}
/* The status column was 6rem, sized by the spec for a chip alone. It has since
   also had to hold "Remove from guest list" (the PR #46 rename) and an "Email
   them" checkbox, and at 6rem the button rendered 96px wide and SIX lines tall.
   11rem fits the button on two lines and the checkbox label on one. */
.roster-table .table-head,.roster-table .roster-row{display:grid;
  grid-template-columns:minmax(0,1fr) 14rem 11rem;gap:1rem}
/* Full-width submit is right for a form's primary action and wrong for a row
   control stacked in a narrow column, where it stretches the label into a
   multi-line block. Out-specifies form button[type=submit] (0,1,2). */
.roster-table form button[type=submit]{width:100%;padding:.5rem .4rem;
  font-size:.625rem;letter-spacing:.1em;line-height:1.35}
/* "Email them" is a checkbox caption, not a form label above a field: keep it
   on one line beside its box instead of inheriting the stacked-label margins. */
.roster-table label.notify{display:flex;min-height:2.75rem;align-items:center;gap:.45rem;
  margin:0 0 .45rem;font-size:.8rem;font-weight:400;line-height:1.3}
.roster-table .table-head{padding:.55rem 0;border-bottom:1px solid var(--ink)}
.roster-table .roster-row{padding:.9rem 0;border-bottom:1px solid var(--line)}
.roster-table .contact{font-size:1.05rem;font-weight:600}
/* An address is one long unbreakable token in a mono face, and the party track
   is only ~10.5rem between the 11rem action column and the 640px stacking
   breakpoint. Without a break rule an ordinary address escapes its column and
   runs into the notes. */
.roster-table .email{display:block;font:400 .75rem/1.5 var(--mono);color:var(--muted);
  overflow-wrap:anywhere}
.roster-table .companions{margin-top:.6rem;padding-left:.9rem;border-left:2px solid var(--line-strong)}
.roster-table .question{font:700 .625rem/1 var(--sans);letter-spacing:.14em;
  text-transform:uppercase;color:var(--muted)}
.badge.maybe{border:1px solid var(--ink);background:transparent;color:var(--ink)}

@media (min-width:34rem){
  .rsvp button[type=submit]{width:auto}
}
@media (max-width:640px){
  body.console,.console{max-width:34rem}
  .field-grid{grid-template-columns:1fr}
  .events-table .table-head,.roster-table .table-head{display:none}
  .events-table .event-row{grid-template-columns:3.75rem 1fr;align-items:start}
  .events-table .event-row>.badge,.events-table .event-row>.count{grid-column:2;text-align:left}
  .roster-table .roster-row{grid-template-columns:1fr}
  .header-band{grid-template-columns:1fr}
  .header-band>section+section{border-left:0;border-top:1px solid var(--line)}
  .label-rail{grid-template-columns:1fr}
  .label-rail .rail-label{padding:1.1rem 0 .4rem}
  .label-rail .rail-fields{padding:.4rem 0 1.1rem}
  .label-rail .rail-label,.label-rail .rail-fields{border-bottom:0}
  .label-rail .rail-fields{border-bottom:1px solid var(--line)}
  .label-rail .rail-label:first-of-type+.rail-fields{border-top:0}
  .create-actions{align-items:flex-start;flex-direction:column}
}
@media (prefers-reduced-motion:reduce){*{transition:none!important}}