/* Collinsville Daily News — Community Calendar (Rendered demo)
   Brand: CDN purple #5f249f + elegant serif wordmark. Clean, ad-free, mobile-first. */

:root{
  /* Per-tenant brand (boot.js overrides both from the tenant's config; the
     --purple-* names stay because 114 call sites speak them — they now mean
     "the paper's accent", derived so every tint follows one hue). */
  --accent:#5f249f;          /* brand hue: washes, tints, borders, display */
  --accent-ink:#5f249f;      /* AA-safe twin: text on white, white on fills */
  --purple:var(--accent-ink); --purple-dark:color-mix(in srgb, var(--accent-ink) 78%, #1c1c1e); --purple-light:var(--accent);
  --purple-wash:var(--neutral-soft);     /* 8/29: tinted surfaces are gray now -- the accent is for branding, not for washes */ --purple-line:var(--neutral-line);
  /* A FOCUS RING IS NOT A WASH. 8/29 pointed --purple-wash at the gray scale,
     which was right for the surfaces it fills (thumbnails, tiles, pills) and
     wrong for the six input rules that were borrowing it as a focus halo: a
     #f1f1f3 glow on a white field is ~1.06:1 and simply is not there. The
     border-color change on those rules still fires, so focus stayed weakly
     indicated rather than absent -- but the halo carried the weight and the
     halo was gone. Its own token now, and one that keeps a hue.

     NOTE, corrected 9/1: a custom property substitutes its var() references at
     computed-value time WHERE IT IS DECLARED, then inherits the resolved value.
     Declaring --focus-ring once on :root would therefore bake in :root's purple
     and .admin's --accent override would never re-resolve it -- the Desk would
     draw a Collinsville ring. Each scope that overrides --accent must redeclare
     --focus-ring too; admin.css does. And the fallback needs @supports, not a
     second declaration: color-mix() is valid custom-property SYNTAX everywhere,
     so a plain override would always win and the rgba would be dead. */
  --focus-ring:rgba(95,36,159,.45);
  --gold:#9a6b12; --gold-soft:#fbf1d8; --gold-line:#e9d39a;
  --ink:#1c1c1e; --muted:#6b6b72;
  --bg:#f7f7f8; --card:#ffffff; --line:#e6e6e9; --field-line:#b9b9c0;
  --shadow:0 1px 2px rgba(28,28,30,.05), 0 6px 22px rgba(28,28,30,.06);
  --shadow-lg:0 10px 40px rgba(28,28,30,.16);
  --serif:'Source Serif 4',Georgia,'Times New Roman',serif;
  --sans:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
  /* state grammar: purple=pitch · green=live · gold=system/monetization chrome */
  --live:#1f9d4d; --live-deep:#1a6b3b; --live-wash:#eafaf0; --live-line:#b8e6c9; --live-text:#1b6e3d;
  --gold-text:#875c0f;            /* gold as TEXT on light (AA-safe) — fills keep --gold */
  --body:#4a4a51;                 /* paragraph copy (~6.5:1) */
  --faint:#6f6f78;                /* was #7a7090 — clears AA on --bg, not just white */
  --header-h:64px;
  /* Owned by assets/safe-area.js, which re-pins them after iOS drops the real
     insets on return from an in-app browser sheet. These env() values are the
     pre-JS fallback so first paint is right even before that file runs. */
  --safe-top:env(safe-area-inset-top, 0px);
  --safe-bottom:env(safe-area-inset-bottom, 0px);
  --safe-left:env(safe-area-inset-left, 0px);
  --safe-right:env(safe-area-inset-right, 0px);
  /* Color discipline (2026-07-26): the accent is EARNED, not ambient.
     It belongs to primary actions, active state, and brand moments. Structure,
     metadata and category chrome use this neutral scale instead — otherwise a
     wall of red or purple flattens the hierarchy and nothing reads first.
     THE BUDGET (2026-08-30). Mark, three rounds in: "the accent-colored
     wordmark along with the near-black buttons and the big gold section is
     just creating a harsh palette." He was right, and the reason it kept
     coming back is that we were fixing one element per round while the COUNT
     of loud things grew: red wordmark, red Submit, red hero word, black List
     block, red chip, gold wash, gold fill, gold outline -- eight, in one
     screen. Nothing was quiet enough to let anything be first.
     Above the fold, allow at most:
       · ONE accent fill  (the primary action)      -- plus the date chip, which is state
       · ONE dark mass    (and prefer none; a segmented control is a light
                           track with a raised white pill, not a black block)
       · ONE gold moment  (the sponsor's own button; the wash, the label and
                           the house ask must not compete with it)
       · accent TEXT is cheap -- the hero city word is the brand moment
     The nameplate is INK. A newspaper's masthead is authority, not decoration.
     Adding a colour is not free: check what it displaces before adding it.

     Addendum (2026-08-29, Mark: "use the papers' accent colors just for branding"):
       · The NEUTRAL SCALE IS NEUTRAL. Until today every gray here was mixed from
         Collinsville's purple (#1c1726 ink, #faf9fc bg, #ece8f2 lines) -- fine
         under a violet accent, muddy under a red one, and it made the black
         toggle read as black-on-violet with gold beside it. Real grays now.
       · Tinted surfaces (session bar, ongoing box, hovers, hairlines) are gray.
         The accent is for brand moments: the wordmark, the hero city word,
         primary buttons, the active date chip, focus, links where AA holds.
     Addendum (2026-08-28, Mark, from his phone: "the red gets overwhelming"):
       · The accent is never a WALL. Measured, the donate band alone was 83%
         of all solid accent on the page; it is now --band (ink), and the
         accent inside it is earned by one button.
       · Fills use the AA twin (--purple = accent-ink), never the raw hue.
       · The accent never sits on a gray surface (--neutral-soft chips, tiles,
         the Share button): ink text there, always.
       · One active accent fill per screen: the view toggle is ink; the date
         chip keeps the accent because it is the state that changes the list. */
  --band:var(--ink);   /* the donate band. If ink reads too heavy on a phone, the
                          deepened brand is one line: color-mix(in srgb, var(--accent-ink) 45%, var(--ink)) */
  --neutral-ink:#3a3a40;      /* metadata that should be readable, not loud */
  --neutral-soft:#f1f1f3;     /* chip + tile fills */
  --neutral-line:#e2e2e6;     /* chip borders, tile edges */
  /* spacing scale (8px base) */
  --space-1:4px; --space-2:8px; --space-3:12px; --space-4:16px;
  --space-5:24px; --space-6:32px; --space-7:48px; --space-8:64px;
  /* radius scale */
  --r-xs:8px; --r-sm:10px; --r-md:14px; --r-lg:18px;
  --shadow-gold:0 1px 2px rgba(28,23,38,.05),0 6px 22px rgba(154,107,18,.12);
  --t:.15s;
}

/* Real ring where color-mix exists; the rgba above stands in where it does not. */
@supports (color: color-mix(in srgb, red 50%, transparent)) {
  :root{--focus-ring:color-mix(in srgb, var(--accent) 45%, transparent)}
}
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;font-family:var(--sans);color:var(--ink);background:var(--bg);line-height:1.5;-webkit-font-smoothing:antialiased}
a{color:var(--purple);text-decoration:none}
/* Text links darken and underline on hover. Button-shaped anchors are exempt
   -- and the exemption is a blacklist that has now bitten twice: .cta was the
   band's button class, and every :not() adds CLASS-level specificity, letting
   this quietly outweigh component rules. Mark chased the fallout as "active
   link color" on the gold button (8/19); it was hover all along, since every
   press and every mobile tap includes hover. */
a:not(.btn):not(.a-btn):not(.cta):hover{color:var(--purple-dark);text-decoration:underline;text-underline-offset:2px}
.btn-primary:hover,.btn-primary:active{color:#fff}
.btn-ghost:hover,.btn-ghost:active{color:var(--purple)}
a:focus-visible,button:focus-visible,.chip:focus-visible,.btn:focus-visible,
.viewtoggle button:focus-visible,.evcard:focus-visible,.tile:focus-visible,
.tw-card:focus-visible,[role="button"]:focus-visible,select:focus-visible,
.skip-link:focus-visible{outline:2px solid var(--purple-light);outline-offset:2px}
.evcard:focus-visible,.tile:focus-visible{border-color:var(--purple-light)}
img{max-width:100%;display:block}
.wrap{max-width:1080px;margin:0 auto;padding:0 var(--space-4)}
@media(min-width:768px){.wrap{padding:0 var(--space-5)}}
@media(max-width:400px){.wrap{padding:0 var(--space-3)}}
.serif{font-family:var(--serif)}

/* ---------- Shared a11y utilities ---------- */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);clip-path:inset(50%);white-space:nowrap;border:0}
.skip-link{position:absolute;left:-9999px;top:0;z-index:200;background:var(--purple);color:#fff;padding:10px 16px;border-radius:0 0 8px 0;font-weight:700}
.skip-link:focus{left:0}

/* ---------- Header ---------- */
.site-header{position:sticky;top:0;z-index:50;background:rgba(255,255,255,.92);backdrop-filter:saturate(180%) blur(10px);border-bottom:1px solid var(--line)}
.state-demo .site-header{background:rgba(252,247,238,.92);border-bottom:1px solid var(--gold-line)}
/* the header is the persistent state-cue anchor — keep it sticky; do not move the pill out of it */
.site-header .wrap{display:flex;align-items:center;justify-content:space-between;height:var(--header-h);gap:12px}
.brand{display:flex;align-items:center;gap:10px;min-width:0}
.brand img{height:34px;width:auto}
.brand .sep{width:1px;height:26px;background:var(--purple-line);margin:0 2px}
.brand .kicker{font-size:13px;color:var(--muted);font-weight:500;white-space:nowrap;letter-spacing:.01em}
.statepill{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:800;
  letter-spacing:.06em;text-transform:uppercase;padding:4px 9px;border-radius:999px;white-space:nowrap;line-height:1.2}
.state-demo .statepill{background:var(--live-wash);color:var(--live-text);border:1px solid var(--live-line)}
.state-demo .statepill::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--live);flex-shrink:0}
.state-overview .statepill,.state-teaser .statepill{background:var(--purple-wash);color:var(--purple);border:1px solid var(--purple-line)}
.header-actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap;justify-content:flex-end}  /* wraps so the masthead never yields when the mod pill joins Submit */
.btn{display:inline-flex;align-items:center;gap:7px;font-family:var(--sans);font-size:14px;font-weight:600;border-radius:var(--r-sm);padding:9px 15px;border:1px solid transparent;cursor:pointer;transition:transform var(--t) ease,box-shadow var(--t) ease,background var(--t) ease,border-color var(--t) ease;white-space:nowrap}
.btn-primary{background:var(--purple);color:#fff}
.btn-primary:hover{background:var(--purple-dark)}
.btn-ghost{background:#fff;color:var(--purple);border-color:var(--purple-line)}
.btn-ghost:hover{background:var(--purple-wash)}
/* Secondary, neutral: white card, ink text, hairline -- the chip/tile recipe. Until
   8/28 .btn-out existed only as .donateband .btn-out, so the Share button outside the
   band fell to Safari's UA defaults (buttonface gray + system blue). */
.btn-out{background:var(--card);color:var(--ink);border-color:var(--neutral-line);-webkit-appearance:none;appearance:none;-webkit-tap-highlight-color:transparent}
.btn-out:hover,.btn-out:active{background:var(--neutral-soft);color:var(--ink)}
.btn-out svg{color:var(--muted)}
.btn-sm{padding:7px 12px;font-size:13px;border-radius:9px}

/* ---------- Hero ---------- */
.hero{padding:var(--space-6) 0 var(--space-4);text-align:center}
.hero h1{font-family:var(--serif);font-weight:800;font-size:clamp(24px,4vw,36px);
  line-height:1.1;margin:0 0 8px;letter-spacing:-.01em}
.hero h1 .accent{color:var(--purple)}
.hero p{color:var(--body);font-size:clamp(15px,2.2vw,17px);margin:0 auto;max-width:560px}

/* One-time snapshot note: a slim, dismissible pill. Seen once, then the x removes it for good (remembered),
   so it never persistently sits above the calendar or crowds the first impression. */
.snapnote{display:flex;align-items:center;gap:7px;width:fit-content;max-width:100%;margin:12px auto 0;
  padding:5px 7px 5px 13px;background:var(--purple-wash);border:1px solid var(--purple-line);border-radius:999px;
  color:var(--purple-dark);font-size:12.5px;line-height:1.3}
.snapnote svg{flex-shrink:0;color:var(--purple)}
.snapnote .snap-txt{min-width:0}
.snapnote b{font-weight:700;white-space:nowrap}
.snapnote-x{flex-shrink:0;width:20px;height:20px;display:flex;align-items:center;justify-content:center;padding:0;
  border:0;background:transparent;color:var(--purple);font-size:17px;line-height:1;cursor:pointer;border-radius:50%;
  opacity:.6;transition:opacity var(--t) ease,background var(--t) ease}
.snapnote-x:hover{opacity:1;background:#fff}
.snapnote[hidden]{display:none}

/* ---------- Live calendar app frame (demo only) ---------- */
.state-demo .appframe{position:relative;background:#fff;border:1px solid var(--line);
  border-radius:var(--r-lg);box-shadow:var(--shadow);padding:46px 18px 22px;margin:6px 0 0}
.state-demo .appframe::before{content:var(--frame-caption, "Live calendar");
  position:absolute;top:0;left:0;right:0;height:34px;display:flex;align-items:center;gap:7px;
  padding:0 16px;font-size:11.5px;font-weight:700;color:var(--muted);
  background:linear-gradient(180deg,var(--bg),#fff);border-bottom:1px solid var(--line);
  border-radius:var(--r-lg) var(--r-lg) 0 0}
.state-demo .appframe>.toolbar{margin-top:0}
.state-demo .appframe .toolbar{background:#fff}
/* toolbar is sticky top:64px — inside the padded frame it still pins to viewport, which is correct */
@media(max-width:680px){
  .state-demo .appframe{padding:38px 18px 16px;border-radius:var(--r-md)}
  .state-demo .appframe::before{height:32px;font-size:11.5px}
}

/* ---------- Breadcrumb (demo only) ---------- */
.crumb{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--muted);padding-top:12px}
.crumb ol{list-style:none;margin:0;padding:0;display:flex;align-items:center;gap:8px}
.crumb li{display:flex;align-items:center;gap:8px}
.crumb a{color:var(--purple);font-weight:600}
.crumb a:hover{text-decoration:underline;text-underline-offset:2px}
.crumb b{color:var(--ink);font-weight:700}
.crumb span{color:var(--faint)}
.crumb [aria-current="page"]{color:var(--ink);font-weight:700}

/* ---------- Toolbar / filters ---------- */
.toolbar{position:sticky;top:var(--header-h);z-index:40;background:var(--bg);padding:var(--space-3) 0}
.searchrow{display:flex;gap:var(--space-3);margin-bottom:var(--space-3)}
.search{flex:1;position:relative}
.search input{width:100%;height:48px;border:1px solid var(--field-line);border-radius:var(--r-sm);
  padding:0 16px 0 44px;font-size:16px;font-family:var(--sans);background:#fff;color:var(--ink);
  box-shadow:var(--shadow);-webkit-appearance:none;appearance:none;background-clip:padding-box}
.search input:focus{outline:none;border-color:var(--purple-light);box-shadow:0 0 0 3px var(--focus-ring)}
.search svg{position:absolute;left:15px;top:15px;color:var(--faint)}
.viewtoggle{display:flex;background:var(--neutral-soft);border:1px solid var(--neutral-line);border-radius:12px;padding:4px;box-shadow:none}
.viewtoggle button{border:0;background:none;padding:0 13px;height:auto;min-height:38px;padding-top:7px;padding-bottom:7px;border-radius:9px;cursor:pointer;color:var(--muted);font-weight:600;font-size:13px;display:flex;align-items:center;gap:6px;font-family:var(--sans)}
.viewtoggle button.active{background:var(--card);color:var(--ink);font-weight:700;box-shadow:0 1px 2px rgba(28,28,30,.10),0 0 0 1px rgba(28,28,30,.05)}   /* selected = raised white on the track, the way a segmented control reads */
.viewtoggle button:hover:not(.active){color:var(--purple);background:var(--purple-wash)}
.chips{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.chip{border:1px solid var(--field-line);background:#fff;color:var(--ink);border-radius:999px;padding:8px 14px;font-size:13.5px;font-weight:600;cursor:pointer;transition:border-color var(--t) ease,background var(--t) ease,color var(--t) ease;font-family:var(--sans)}
.chip:hover{border-color:var(--purple-light)}
.btn:active,.chip:active,.viewtoggle button:active{transform:translateY(1px)}
.chip.active{background:var(--purple);border-color:var(--purple);color:#fff;font-weight:800}
.chip-div{width:1px;height:22px;background:var(--line);margin:0 3px}
.catselect{margin-left:auto}
.catselect select{height:44px;border:1px solid var(--field-line);border-radius:var(--r-sm);background:#fff;
  padding:0 40px 0 14px;font-size:16px;font-weight:600;color:var(--ink);font-family:var(--sans);cursor:pointer;
  appearance:none;-webkit-appearance:none;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236c6480' stroke-width='3'><path d='M6 9l6 6 6-6'/></svg>");
  background-repeat:no-repeat;background-position:right 15px center}
.resultcount{color:var(--muted);font-size:14px;margin:var(--space-4) 2px var(--space-2)}

/* ---------- Featured spotlight ---------- */
.spotlight{position:relative;border-radius:var(--r-lg);overflow:hidden;margin:var(--space-2) 0 var(--space-5);box-shadow:var(--shadow-lg);min-height:230px;display:flex;align-items:flex-end;color:#fff;background:#2a1640}
.spotlight img.bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:.72}
.spotlight .grad{position:absolute;inset:0;background:linear-gradient(180deg,rgba(42,22,64,.32) 0%,rgba(42,22,64,.46) 50%,rgba(30,14,48,.9) 100%)}
.spotlight svg{width:15px;height:15px;flex-shrink:0}
.spotlight .inner{position:relative;padding:var(--space-5) var(--space-5);width:100%}
.spotlight .tag{display:inline-flex;align-items:center;gap:6px;background:var(--gold);color:#241700;font-weight:800;font-size:12px;letter-spacing:.08em;text-transform:uppercase;padding:5px 11px;border-radius:999px;margin-bottom:12px}
.spotlight h2{font-family:var(--serif);font-weight:800;font-size:clamp(22px,3.6vw,32px);margin:0 0 8px;line-height:1.12;text-shadow:0 1px 3px rgba(0,0,0,.4)}
.spotlight .meta{font-size:15px;opacity:1;color:#fff;display:flex;flex-wrap:wrap;gap:var(--space-2) var(--space-4);margin-bottom:var(--space-4);text-shadow:0 1px 2px rgba(0,0,0,.55)}
.spotlight .meta b{font-weight:700}

/* ---------- List view ---------- */
.daygroup{margin-bottom:var(--space-6)}
:root{--dayhead-top:188px}
@media(max-width:768px){:root{--dayhead-top:120px}}
/* Unpinned below 900px: a pinned bar broke because the collapsing categories
   row shifts every card up by the collapse height, sliding the first card
   under a bar frozen at the tall-toolbar position. At >=900px the chip row
   never collapses, so the date rail (print-calendar section below) pins
   against --dayhead-top — which app.js syncStickyTop() keeps synced to the
   toolbar's bottom edge. That JS is this variable's only maintainer: not dead
   code. */
.dayhead{display:flex;align-items:center;gap:10px;margin:0 0 14px;padding:9px 15px;background:var(--neutral-soft);border:1px solid var(--neutral-line);border-radius:12px}
.dayhead .d{font-family:var(--serif);font-weight:700;font-size:19px}
.dayhead .dd{color:var(--muted);font-size:13.5px;font-weight:500}
.dayhead .today{background:var(--purple);color:#fff;font-size:11px;font-weight:800;letter-spacing:.04em;padding:3px 9px;border-radius:999px;text-transform:uppercase}
.evlist{list-style:none;margin:0;padding:0}

.evcard{position:relative;display:flex;gap:var(--space-4);background:var(--card);border:1px solid var(--line);
  border-radius:var(--r-md);padding:var(--space-4);margin-bottom:var(--space-3);cursor:pointer;
  transition:transform var(--t) ease,box-shadow var(--t) ease,border-color var(--t) ease;box-shadow:var(--shadow)}
.evcard:hover{border-color:var(--purple-line);box-shadow:var(--shadow-lg);transform:translateY(-1px)}
.evcard .thumb{width:108px;height:96px;border-radius:10px;object-fit:cover;flex-shrink:0;background:var(--purple-wash)}
.evcard .time{flex-shrink:0;width:74px;text-align:center;padding-top:3px}
.evcard .time .t{font-weight:800;font-size:16px;color:var(--purple);line-height:1.1}
.evcard .time .ampm{font-size:11px;font-weight:700;color:var(--muted);letter-spacing:.04em}
.evcard .body{min-width:0;flex:1}
.evcard h3{font-family:var(--serif);font-weight:700;font-size:18px;margin:1px 0 5px;line-height:1.28}
.evcard .where{color:var(--muted);font-size:13px;margin-bottom:8px;display:flex;align-items:center;gap:6px}
.evcard .when{font-size:12.5px;font-weight:800;color:var(--neutral-ink);letter-spacing:.01em;margin:0 0 3px}
.evcard .when-t{color:var(--muted);font-weight:600}
.evcard .badges{display:flex;gap:7px;flex-wrap:wrap;align-items:center}
.cat{font-size:11.5px;font-weight:700;color:var(--neutral-ink);background:var(--neutral-soft);border:1px solid var(--neutral-line);padding:3px 9px;border-radius:999px;letter-spacing:.01em}
.free{font-size:11.5px;font-weight:700;color:var(--live-deep);background:#e6f6ec;padding:3px 9px;border-radius:999px}
.cost{font-size:11.5px;font-weight:700;color:var(--ink);background:#f0edf6;padding:3px 9px;border-radius:999px}
.sponsor{font-size:11.5px;font-weight:700;color:var(--gold-text);background:var(--gold-soft);border:1px solid var(--gold-line);padding:3px 9px;border-radius:999px;display:inline-flex;align-items:center;gap:5px}
.sponsor svg{width:11px;height:11px}

/* ---------- Print-calendar date rail (>=900px): the day owns a column, like a
   paper's week grid — reclaimed width becomes composition, not a wider
   stretched card. Gated at 900: below that the collapsing chip row shifts
   cards under a pinned bar (the original unpinning bug, see note at
   --dayhead-top); at >=900 the chip row never collapses, so the rail pins
   safely against --dayhead-top — which app.js syncStickyTop() keeps synced to
   the toolbar's bottom edge. Applies to the demo too, inside its frame — the
   pitch shows the real product. The Ongoing block and the ad slot sit outside
   .daygroup and keep spanning full width. ---------- */
@media(min-width:900px){
  .daygroup{display:grid;grid-template-columns:132px minmax(0,1fr);column-gap:20px}
  .dayhead{display:block;position:sticky;top:var(--dayhead-top);align-self:start;
    background:none;border:0;border-radius:0;padding:2px 0 0;margin:0}
  .dayhead .d{display:block;font-size:22px;line-height:1.15}
  .dayhead .dd{display:block;font-size:13px;margin-top:2px}
  .dayhead .today{display:inline-block;margin-top:8px}
}
/* Two-up day listing (>=1100px): row-major reading order equals time order,
   and every card already prints its own day+time stamp (.when), so chronology
   survives the split. 1100 not 900: below that the halved column starves the
   card body once the 108px thumb takes its share. */
@media(min-width:1100px){
  .evlist{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));column-gap:16px;align-items:start}
}

/* ---------- Grid view ---------- */
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:var(--space-4);list-style:none;margin:0;padding:0}
.tile{background:var(--card);border:1px solid var(--line);border-radius:var(--r-md);overflow:hidden;cursor:pointer;transition:transform var(--t) ease,box-shadow var(--t) ease,border-color var(--t) ease;box-shadow:var(--shadow);display:flex;flex-direction:column}
.tile:hover{border-color:var(--purple-line);box-shadow:var(--shadow-lg);transform:translateY(-2px)}
.tile .pic{aspect-ratio:16/10;width:100%;object-fit:cover;background:var(--purple-wash)}
.tile .tbody{padding:var(--space-4);display:flex;flex-direction:column;gap:var(--space-2);flex:1}
.tile .dt{font-size:13px;font-weight:700;color:var(--purple);text-transform:uppercase;letter-spacing:.04em}
.tile h3{font-family:var(--serif);font-weight:700;font-size:17px;margin:0;line-height:1.28}
.tile .where{color:var(--muted);font-size:13px;margin-top:auto}
.tile .badges{display:flex;gap:6px;flex-wrap:wrap;margin-top:2px}

/* ---------- Map view ---------- */
#map{height:560px;border-radius:16px;border:1px solid var(--line);box-shadow:var(--shadow);z-index:1}
.leaflet-popup-content{margin:12px 14px;font-family:var(--sans)}
.mappop h4{font-family:var(--serif);font-size:15px;margin:0 0 4px;line-height:1.18}
.mappop .mp-meta{font-size:12.5px;color:var(--muted);margin-bottom:8px}
.mappop .mp-links{display:flex;flex-wrap:wrap;gap:12px;margin-top:2px}
.mappop .mp-link{font-weight:700;font-size:13px;color:var(--purple);background:none;border:0;padding:0;cursor:pointer;text-decoration:underline;font-family:var(--sans)}

/* ---------- Modal ---------- */
.modal-back{position:fixed;inset:0;background:rgba(28,18,40,.55);backdrop-filter:blur(3px);z-index:100;display:none;align-items:flex-start;justify-content:center;overflow-y:auto;padding:calc(var(--space-5) + var(--safe-top)) var(--space-4) calc(var(--space-5) + var(--safe-bottom))}
.modal-back.open{display:flex}
.modal{background:#fff;border-radius:20px;max-width:620px;width:100%;box-shadow:var(--shadow-lg);overflow:hidden;animation:pop .2s ease}
@keyframes pop{from{transform:translateY(14px);opacity:0}to{transform:none;opacity:1}}
.modal .hero-img{width:100%;height:260px;object-fit:cover;background:var(--purple-wash);display:block}
.modal .hero-wrap{display:block;position:relative;width:100%;padding:0;border:0;background:none;cursor:zoom-in;overflow:hidden}
.modal .hero-zoom{position:absolute;right:12px;bottom:12px;width:34px;height:34px;border-radius:9px;background:rgba(18,10,28,.5);color:#fff;display:flex;align-items:center;justify-content:center;pointer-events:none;transition:background var(--t) ease}
.modal .hero-wrap:hover .hero-zoom,.modal .hero-wrap:focus-visible .hero-zoom{background:rgba(18,10,28,.82)}
.modal .hero-wrap:focus-visible{outline:2px solid var(--purple-light);outline-offset:-3px}
.lightbox{position:fixed;inset:0;z-index:200;display:flex;align-items:center;justify-content:center;
  padding:calc(24px + var(--safe-top)) 24px calc(24px + var(--safe-bottom));
  background:rgba(18,10,28,.88);opacity:0;transition:opacity .18s ease;cursor:zoom-out;-webkit-tap-highlight-color:transparent}
.lightbox.show{opacity:1}
.lightbox img{max-width:96vw;max-height:92vh;width:auto;height:auto;border-radius:10px;box-shadow:0 24px 70px rgba(0,0,0,.55);object-fit:contain}
.lb-close{position:absolute;top:calc(16px + var(--safe-top));right:16px;width:42px;height:42px;border-radius:50%;background:rgba(255,255,255,.94);border:0;cursor:pointer;font-size:26px;line-height:1;color:var(--ink);display:flex;align-items:center;justify-content:center;box-shadow:0 4px 14px rgba(0,0,0,.3)}
.lb-close:hover{background:#fff}
.lb-close:focus-visible{outline:2px solid #fff;outline-offset:3px}
.spotlight .sl-zoom{position:absolute;top:12px;right:12px;z-index:2;width:34px;height:34px;border-radius:9px;background:rgba(18,10,28,.5);color:#fff;border:0;cursor:zoom-in;display:flex;align-items:center;justify-content:center;transition:background var(--t) ease}
.spotlight .sl-zoom:hover{background:rgba(18,10,28,.85)}
.spotlight .sl-zoom:focus-visible{outline:2px solid #fff;outline-offset:2px}
.modal .mclose{position:absolute;top:14px;right:14px;width:38px;height:38px;border-radius:50%;background:rgba(255,255,255,.92);border:1px solid var(--line);cursor:pointer;font-size:22px;line-height:1;color:var(--ink);display:flex;align-items:center;justify-content:center;box-shadow:var(--shadow)}
.modal .mclose:hover{background:#fff;color:var(--purple-dark)}
.modal .mclose:focus-visible{outline:2px solid var(--purple-light);outline-offset:2px}
.modal .mbody{padding:var(--space-5)}
.modal .ribbon{display:inline-flex;align-items:center;gap:6px;background:var(--gold);color:#241700;font-weight:800;font-size:12px;letter-spacing:.08em;text-transform:uppercase;padding:5px 11px;border-radius:999px;margin-bottom:12px}
.modal .ribbon svg{width:12px;height:12px}
.modal h2{font-family:var(--serif);font-weight:800;font-size:26px;margin:0 0 14px;line-height:1.12}
.mrow{display:flex;gap:12px;align-items:flex-start;margin-bottom:var(--space-3);font-size:14.5px}
.mrow svg{color:var(--muted);flex-shrink:0;margin-top:2px}
.mrow .lbl{color:var(--ink)}
.mrow .sub{color:var(--muted);font-size:13px}
.maplinks{display:flex;flex-wrap:wrap;gap:14px;margin-top:8px}
.maplink{display:inline-flex;align-items:center;gap:5px;padding:0;border:0;background:none;font:inherit;font-size:13px;font-weight:700;color:var(--neutral-ink);cursor:pointer;text-decoration:none}
.maplink:hover,.maplink:focus-visible{color:var(--purple)}
.maplink svg{width:14px;height:14px}
.maplink:hover{text-decoration:underline}
.mdesc{color:#3a3349;font-size:14.5px;line-height:1.62;margin:16px 0;white-space:pre-line}
.mpresented{background:var(--gold-soft);border:1px solid var(--gold-line);border-radius:12px;padding:12px 15px;margin:14px 0;display:flex;align-items:center;gap:10px;font-size:13.5px}
.mpresented .ico{width:30px;height:30px;border-radius:8px;background:var(--gold);color:#241700;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.mpresented .ico svg{width:16px;height:16px}
.mpresented b{color:var(--gold-text)}
.mactions{display:flex;gap:var(--space-3);flex-wrap:wrap;margin-top:var(--space-5);
  padding-top:var(--space-5);border-top:1px solid var(--line)}
.mbadges{display:flex;gap:7px;flex-wrap:wrap;margin-bottom:4px}

/* ---------- Submit form ---------- */
/* > .field min-width:0: same WebKit track-floor overflow the Desk's .fld hit
   (admin.css has the full story) — the public form now carries a poster
   preview and one wide child would push every field off a phone's right edge
   there too. Zero effect in engines that already exempt scroll containers. */
.form-grid{display:grid;gap:var(--space-4)}
.form-grid > .field{min-width:0}
.field label{display:block;font-size:13px;font-weight:700;margin-bottom:5px;color:var(--ink)}
.field input,.field textarea,.field select{width:100%;border:1px solid var(--field-line);
  border-radius:var(--r-sm);padding:12px 14px;font-size:16px;line-height:1.3;font-family:var(--sans);
  color:var(--ink);background:#fff;-webkit-appearance:none;appearance:none;background-clip:padding-box;min-height:46px}
.field select{background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236c6480' stroke-width='3'><path d='M6 9l6 6 6-6'/></svg>");background-repeat:no-repeat;background-position:right 15px center;padding-right:40px}
.field input:focus,.field textarea:focus,.field select:focus,.catselect select:focus{
  outline:none;border-color:var(--purple-light);box-shadow:0 0 0 3px var(--focus-ring)}
/* native date/time controls ignore line-height/padding on iOS — pin height + appearance */
.field input[type=date],.field input[type=time]{-webkit-appearance:none;appearance:none;min-height:46px;line-height:1.3}
.field input[type=date]::-webkit-date-and-time-value{text-align:left}
.two{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-3)}
.confirm{text-align:center;padding:30px 10px}
.confirm .ck{width:62px;height:62px;border-radius:50%;background:#e6f6ec;color:#1f7a44;display:flex;align-items:center;justify-content:center;margin:0 auto 16px}
.confirm h2{font-family:var(--serif);margin:0 0 8px;line-height:1.18}
.confirm p{color:var(--muted);margin:0 auto;max-width:340px}
.hint{font-size:12.5px;color:var(--muted);margin-top:6px}
.hint-ok{color:#1f7a44;font-weight:600}
.hint svg{width:13px;height:13px;vertical-align:-2px;margin-right:2px}
.fopt{color:var(--muted);font-weight:400}
.field input[type=file]{border:1px dashed var(--field-line);background:var(--bg);padding:10px 12px;font-size:13.5px;color:var(--muted);cursor:pointer}
.field input[type=file]::file-selector-button{font:inherit;font-weight:700;font-size:13px;color:var(--purple);background:var(--purple-wash);border:1px solid var(--purple-line);border-radius:8px;padding:8px 14px;margin-right:12px;cursor:pointer;transition:background var(--t) ease}
.field input[type=file]::file-selector-button:hover{background:#ece1f7}
.form-intro{color:var(--muted);margin:0 0 18px;font-size:14.5px}
.field input[aria-invalid="true"],.field textarea[aria-invalid="true"],.field select[aria-invalid="true"]{border-color:#b3261e;box-shadow:0 0 0 3px #fbe9e7}
.field-error{color:#b3261e;font-size:13px;font-weight:600;margin-top:5px}
.search input::placeholder,.field input::placeholder,.field textarea::placeholder{color:#5f586e;opacity:1}

/* ---------- Footer ---------- */
/* The home indicator eats the last row. Nothing here reserved space for it, so
   the maker credit — and part of the Admin link — sat under it on a notched
   phone (Mark, 8/5). --safe-bottom is JS-pinned (assets/safe-area.js) and is
   0 anywhere without an inset, so this costs desktop nothing. */
.site-footer{margin-top:var(--space-6);border-top:1px solid var(--neutral-line);background:var(--bg);   /* the page ground, not a white step: share, links and credit are one quiet tail */
  padding:var(--space-5) 0 calc(var(--space-5) + var(--safe-bottom));
  text-align:center;color:var(--muted);font-size:13px}
.site-footer .credit{margin-top:8px;font-size:13px;color:var(--muted)}
/* Rendered Digital footer lockup — the sanctioned maker credit (rendereddigital.io family convention) */
.footer-credit{margin-top:14px;font-size:12px;color:var(--muted)}
.rendered-lockup{display:inline-flex;align-items:center;gap:.4em;text-decoration:none;color:var(--muted)}
.rendered-lockup:hover,.rendered-lockup:focus-visible{color:var(--purple)}
.rendered-prism{width:1.15em;height:1.15em;flex-shrink:0;vertical-align:middle}
.rendered-verb{font-weight:400;letter-spacing:normal}
.rendered-wordmark{font-weight:700;letter-spacing:.15em;text-transform:uppercase;font-size:.85em}
.empty{text-align:center;padding:var(--space-7) var(--space-5);color:var(--muted)}
.empty .serif{font-size:20px;color:var(--ink);margin-bottom:6px;display:block}

/* ---------- Demo / state banner ---------- */
.demobar{display:flex;align-items:center;justify-content:center;gap:8px;text-align:center;
  font-size:12.5px;font-weight:600;padding:calc(var(--space-2) + var(--safe-top)) var(--space-4) var(--space-2);letter-spacing:.01em;line-height:1.4}
.demobar b{font-weight:800}
/* PITCH state (overview + teaser): purple */
.state-overview .demobar,.state-teaser .demobar{
  background:linear-gradient(90deg,var(--purple),var(--purple-light));color:#fff}
/* LIVE state (calendar): gold system bar + pulsing green dot */
.state-demo .demobar{background:var(--gold-soft);color:#5a3d07;border-bottom:1px solid var(--gold-line)}
.state-demo .demobar b{color:var(--gold-text)}
.state-demo .demobar::before{content:"";width:7px;height:7px;border-radius:50%;background:var(--live);
  box-shadow:0 0 0 0 rgba(31,157,77,.5);animation:livepulse 2s infinite;flex-shrink:0}
@keyframes livepulse{0%{box-shadow:0 0 0 0 rgba(31,157,77,.5)}70%{box-shadow:0 0 0 6px rgba(31,157,77,0)}100%{box-shadow:0 0 0 0 rgba(31,157,77,0)}}
@media(prefers-reduced-motion:reduce){.state-demo .demobar::before{animation:none}}

@media(max-width:680px){
  :root{--header-h:56px}
  .brand .kicker{display:none}
  .hero{padding:var(--space-5) 0 var(--space-3)}
  .searchrow{flex-direction:column}
  .viewtoggle{align-self:stretch}
  .viewtoggle button{flex:1;justify-content:center;height:44px}
  .evcard{gap:var(--space-3);padding:var(--space-3)}
  .evcard .thumb{width:84px;height:84px}
  .evcard .time{display:none}
  .catselect{margin-left:0;width:100%}
  .catselect select{width:100%;height:44px}
  .chip{padding:11px 15px;font-size:14px}
  #map{height:440px}
  .demobar{font-size:12px;line-height:1.4}
  .modal-back{padding:calc(var(--space-3) + var(--safe-top)) var(--space-3) calc(var(--space-3) + var(--safe-bottom))}
  .modal{border-radius:var(--r-md)}
  .modal .hero-img{height:200px}
  .modal .mbody{padding:var(--space-4)}
  .modal h2{font-size:22px}
  .spotlight .inner{padding:var(--space-5) var(--space-4)}
  .spotlight{min-height:200px}
  .donateband,.whatsnext{padding:var(--space-5) var(--space-4)}
  .empty{padding:var(--space-6) var(--space-4)}
}

/* ---------- Monetization — every surface is revenue SHE keeps ---------- */
/* CTA buttons (were <a>, now real <button> — keep their look) */
.cta{font:inherit;cursor:pointer}
.adslot .cta,.sponsorband .cta{border-width:1px;border-style:solid}
.adslot .cta{border-color:var(--purple)}
.adslot .cta:hover{border-color:var(--purple-dark)}
/* Calendar sponsor (premium top slot) */
.sponsorband{display:flex;align-items:center;gap:14px;background:var(--card);border:1px solid var(--gold-line);border-radius:var(--r-md);padding:var(--space-3) var(--space-4);margin:0 0 var(--space-5)}   /* a white card with a gold edge: one gold MOMENT (their button), not a gold section */
.sponsorband .lab{font-size:11px;font-weight:800;letter-spacing:.09em;text-transform:uppercase;color:var(--gold-text);background:var(--gold-soft);border:1px solid transparent;padding:5px 9px;border-radius:7px;white-space:nowrap;text-align:center;line-height:1.25}
.sponsorband .txt{font-size:14px;color:var(--ink);flex:1;line-height:1.35;min-width:0}
.sponsorband .txt b{font-family:var(--serif);font-weight:700;line-height:1.18}
/* The sponsor's NAME is the band's headline; the sentence is a kicker above
   it. Sized so the name outweighs everything else in the box, because the
   name is the thing that was bought (Mark, 8/19). */
.sponsorband .sp-kick{display:block;font-size:12px;color:var(--muted);margin-bottom:2px}
.sponsorband .sp-name{display:block;font-size:20px;line-height:1.15;letter-spacing:-.01em}
.sponsorband .sp-name a{color:var(--ink);text-decoration:none}
.sponsorband .sp-name a:hover,.sponsorband .sp-name a:focus-visible{color:var(--purple)}
.sponsorband .txt .sub{color:var(--muted);font-size:13px;display:block;margin-top:3px}
.sponsorband .cta{font-size:12.5px;font-weight:700;color:var(--gold-text);white-space:nowrap;border:1px solid var(--gold-line);background:#fff;border-radius:9px;padding:8px 13px}
.sponsorband .cta:hover{background:var(--gold-soft)}
/* The sponsor's own link is the card's loud action: filled gold, WHITE ink.
   Measured, not eyeballed -- gold with the ribbon's brown ink is 3.75:1,
   which is fine for a 12px uppercase pill and short of the 4.5:1 that
   button-sized text owes; white on the same gold is 4.68:1. Wraps rather
   than overflows, because a sponsor name can be long and 390px is a gate. */
.sponsorband .sp-visit{background:var(--ink);border-color:var(--ink);color:#fff;
  font-weight:800;text-decoration:none;display:inline-flex;align-items:center;gap:7px;
  white-space:normal;overflow-wrap:anywhere;max-width:100%}
.sponsorband .sp-visit:hover{background:var(--ink);filter:brightness(1.35)}
/* Pressed/tapped states are DELIBERATE, not platform defaults: without these,
   iOS flashes its gray tap-highlight over the gold, and any state that drops
   the button's own color falls back to the global link color -- which on a
   red-accent paper is red on gold (Mark, 8/19: "clashes badly"). */
.sponsorband a,.sponsorband .cta{-webkit-tap-highlight-color:transparent}
.sponsorband .sp-name a:active{color:var(--purple)}
/* a.sp-visit ties the global hover rule's :not()-inflated specificity and
   wins on order -- armor in case the exemption list ever regresses. */
.sponsorband a.sp-visit:hover,.sponsorband a.sp-visit:active{color:#fff;text-decoration:none}
.sponsorband .sp-visit:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
.sponsorband .sp-visit:active{background:var(--gold);color:#fff;filter:brightness(.94)}
.sponsorband .sp-visit:visited{color:#fff}
.sponsorband .sp-visit:focus-visible{outline:2px solid var(--gold-text);outline-offset:2px}
.sponsorband .sp-buy:active{background:var(--gold-soft);color:var(--gold-text)}
.sponsorband .sp-visit .sp-arr{font-weight:700}
.sponsorband .sp-logo-link{flex-shrink:0;line-height:0;display:block}
/* House "buy this spot" is the quieter of the two -- it must never out-shout
   the business that actually paid. */
.sponsorband .sp-buy{font-weight:600;color:var(--neutral-ink);background:transparent;border-color:transparent;text-decoration:underline;text-underline-offset:3px;padding-left:4px;padding-right:4px}   /* the HOUSE ask is a link, not a second gold button beside the sponsor's */
.sponsorband .sp-buy:hover{background:var(--gold-soft)}

/* Native in-feed ad slot (sold + kept by the paper) */
.adslot{display:flex;gap:15px;align-items:center;background:#fff;border:1px dashed var(--purple-line);border-radius:var(--r-md);padding:var(--space-4);margin:0 0 var(--space-3);position:relative}
.adslot .slotlab{position:absolute;top:-8px;left:15px;font-size:11px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);background:var(--bg);padding:1px 8px;border:1px solid var(--line);border-radius:6px}
.adslot .ico{width:48px;height:48px;border-radius:12px;background:var(--purple-wash);color:var(--purple);display:flex;align-items:center;justify-content:center;flex-shrink:0}
.adslot .body{flex:1;min-width:0}
.adhead{font-family:var(--serif);font-size:16px;margin:0 0 3px;line-height:1.18}
.adslot p{margin:0;font-size:13px;color:var(--body);line-height:1.4}
.adslot .cta{font-size:13px;font-weight:700;color:#fff;background:var(--purple);border-radius:9px;padding:10px 15px;white-space:nowrap}
.adslot .cta:hover{background:var(--purple-dark)}

/* Promoted event treatment (a paid feature): a soft gold wash, matching the app's gradient idiom instead of a rail. */
.evcard.promoted{background:linear-gradient(150deg,var(--gold-soft),#fff 70%);border-color:var(--gold-line);box-shadow:var(--shadow-gold)}

/* Support / donate */
.donateband{background:var(--band);color:#fff;border-radius:var(--r-lg);padding:var(--space-6);margin:var(--space-6) 0 var(--space-2);display:flex;align-items:center;justify-content:space-between;gap:20px;flex-wrap:wrap}
.donateband .dt h3{font-family:var(--serif);font-weight:700;font-size:21px;letter-spacing:-.01em;margin:0 0 6px;line-height:1.18}
.donateband .dt p{margin:0;font-size:15px;line-height:1.5;color:rgba(255,255,255,.78);max-width:520px}
.donateband .dbtns{display:flex;gap:10px;flex-wrap:wrap}
.donateband .btn-white{background:#fff;color:var(--purple)}
.donateband .btn-white:hover{background:color-mix(in srgb,var(--accent) 8%,#fff)}   /* was a lavender tint: wrong hue on a red paper */
/* frosted fill, not a hairline ring: on a dark surface a 1px ring is how iOS draws a disabled control */
.donateband .btn-out{background:rgba(255,255,255,.1);color:rgba(255,255,255,.92);border:1px solid transparent}
.donateband .btn-out:hover,.donateband .btn-out:active{background:rgba(255,255,255,.18);color:#fff}
.donateband .btn-white{box-shadow:none}

/* Promote upsell after a submission */
.promo-up{background:var(--gold-soft);border:1px solid var(--gold-line);border-radius:13px;padding:16px 18px;margin-top:20px;text-align:left}
.promo-up h4{font-family:var(--serif);margin:0 0 5px;font-size:17px;line-height:1.18}
.promo-up p{margin:0 0 13px;font-size:13.5px;color:#5a4a2a;line-height:1.45}
.promo-up .row{display:flex;gap:11px;align-items:center;flex-wrap:wrap}
.promo-up .price{font-weight:800;color:var(--gold-text);font-size:16px}

/* Keep a keyboard-focused card clear of the sticky header + toolbar. The
   browser honours scroll-margin on NATIVE focus scrolling, so these are live
   for anyone tabbing -- they were three hardcoded guesses (170/150/140)
   against a real chrome bottom of 277 on a phone, landing a focused card
   137px behind the bar. Same live measurement the day heads pin to, so it
   can never drift again (8/22). */
.evcard,.tile,.spotlight,.adslot,.dayhead{scroll-margin-top:calc(var(--dayhead-top) + 8px)}

@media(max-width:680px){
  /* live papers: trim frame-era air only — the gold label and the "presented
     by" sentence both stay: a paid band keeps its visible disclosure, and it
     keeps the TOP slot it was sold as. */
  .state-live .sponsorband{padding:10px 12px;margin-bottom:var(--space-4)}
  .sponsorband{flex-wrap:wrap;gap:10px}
  .sponsorband .lab{order:1}
  .sponsorband .txt{order:2;flex-basis:100%}
  .sponsorband .sp-visit{order:3}
  .sponsorband .sp-buy{order:4}
  .sponsorband .cta{order:3;flex-basis:100%;text-align:center;min-height:44px;
    display:inline-flex;align-items:center;justify-content:center}
  .donateband{flex-direction:column;align-items:flex-start;gap:16px}
  .donateband .dbtns{flex-direction:column;align-self:stretch;width:100%}
  .donateband .dbtns .btn{justify-content:center;min-height:46px;font-size:15px}
  .whatsnext{flex-direction:column;align-items:flex-start;gap:16px}
  .whatsnext .btn-white{align-self:stretch;text-align:center;justify-content:center}
}

/* ============ COVER PAGE ============ */
.btn-lg{font-size:15.5px;padding:13px 22px;border-radius:var(--r-sm)}
.btn-lg svg{width:16px;height:16px}
.cover-hero{text-align:center;padding:var(--space-7) 0 var(--space-6);max-width:760px;margin:0 auto}
.eyebrow{display:inline-block;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--purple);background:var(--purple-wash);padding:10px 20px;border-radius:999px;margin-bottom:20px;line-height:1.2}
.eyebrow-live{background:var(--live-wash);color:var(--live-text)}
.cover-hero h1{font-family:var(--serif);font-weight:800;font-size:clamp(26px,6.4vw,52px);line-height:1.14;margin:0 0 20px;letter-spacing:-.005em}
.cover-hero h1 .accent{color:var(--purple)}
.cover-hero .lede{font-size:clamp(16px,2.3vw,18.5px);color:#48415a;line-height:1.6;margin:0 auto 26px;max-width:640px}
.cover-hero .lede b{color:var(--ink);font-weight:700}
.cta-row{display:flex;gap:12px;justify-content:center;flex-wrap:wrap}
.freenote{font-size:13px;color:var(--muted);margin:20px auto var(--space-5);max-width:520px}

.props{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--space-4);padding:var(--space-6) 0 0}
.prop{background:var(--card);border:1px solid var(--line);border-radius:16px;padding:var(--space-5);box-shadow:var(--shadow)}
.prop .ic{width:48px;height:48px;border-radius:13px;display:flex;align-items:center;justify-content:center;margin-bottom:14px}
.ic-purple{background:var(--purple-wash);color:var(--purple)}
.ic-gold{background:var(--gold-soft);color:var(--gold)}
.ic-char{font-family:var(--serif);font-weight:800;font-size:27px;line-height:1}
.prop h3{font-family:var(--serif);font-weight:700;font-size:19px;margin:0 0 8px;line-height:1.2}
.prop p{margin:0;font-size:14px;color:var(--body);line-height:1.55}
.prop p b{color:var(--ink)}

.revenue{padding:var(--space-7) 0 0}
.rev-head{text-align:center;max-width:620px;margin:0 auto 22px}
.rev-head h2{font-family:var(--serif);font-weight:800;font-size:clamp(24px,4vw,32px);margin:0 0 8px;line-height:1.18}
.rev-head p{margin:0;color:var(--body);font-size:15px}
.rev-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--space-3)}
.rev-item{background:linear-gradient(180deg,#fff,var(--purple-wash));border:1px solid var(--purple-line);border-radius:var(--r-md);padding:var(--space-4)}
.rev-tag{display:inline-block;font-family:var(--serif);font-weight:700;font-size:16px;color:var(--purple);margin-bottom:7px}
.rev-item p{margin:0;font-size:13px;color:var(--body);line-height:1.5}
/* Payment reassurance beat: how the money actually reaches the publisher (explained, not built into the demo). */
.paynote{margin-top:var(--space-5);background:linear-gradient(150deg,var(--gold-soft),#fff 72%);border:1px solid var(--gold-line);border-radius:var(--r-md);padding:22px 30px;text-align:center}
.paynote h3{font-family:var(--serif);font-weight:700;font-size:19px;margin:0 0 8px;color:var(--ink);line-height:1.2}
.paynote p{margin:0 auto;font-size:14px;color:var(--body);line-height:1.62;max-width:58ch}
.paynote b{color:var(--ink);font-weight:700}

.runit{background:#fff;border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--shadow);padding:var(--space-6);margin:var(--space-7) 0 0;display:flex;align-items:center;justify-content:space-between;gap:var(--space-6);flex-wrap:wrap}
.ri-txt{flex:1;min-width:250px}
.ri-eyebrow{display:inline-block;font-size:11.5px;font-weight:800;letter-spacing:.09em;text-transform:uppercase;color:var(--purple);background:var(--purple-wash);border:1px solid var(--purple-line);padding:5px 11px;border-radius:999px;margin-bottom:13px}
.ri-txt h2{font-family:var(--serif);font-weight:800;font-size:clamp(21px,3.4vw,28px);margin:0 0 8px;line-height:1.14;color:var(--ink)}
.ri-txt p{margin:0;font-size:14.5px;color:var(--body);line-height:1.55;max-width:560px}
.ri-act{display:flex;flex-direction:column;align-items:flex-start;gap:9px;flex-shrink:0}
.ri-note{font-size:12.5px;color:var(--muted)}
@media(max-width:560px){.runit{padding:var(--space-5)}.ri-act{align-items:stretch;width:100%}.ri-act .btn{justify-content:center;text-align:center}}

.whatsnext{background:linear-gradient(120deg,var(--purple),var(--purple-light));color:#fff;border-radius:20px;padding:var(--space-6);margin:var(--space-7) 0 var(--space-2);display:flex;align-items:center;justify-content:space-between;gap:24px;flex-wrap:wrap}
.whatsnext h2{font-family:var(--serif);font-weight:800;font-size:clamp(21px,3.4vw,28px);margin:0 0 7px;line-height:1.12}
.whatsnext p{margin:0;font-size:14.5px;opacity:.93;max-width:560px;line-height:1.55}

/* ============ TEASER / EMBED PAGE ============ */
.siteframe{border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--shadow-lg);background:#fff;margin:8px 0 10px}
.state-teaser .siteframe{position:relative}
.state-teaser .siteframe::before{content:"Your homepage (mock-up)";display:block;
  font-size:11px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;
  color:var(--faint);padding:10px 16px 0}
.sf-bar{display:flex;align-items:center;gap:var(--space-3) var(--space-4);
  padding:var(--space-3) var(--space-4);flex-wrap:wrap;border-bottom:1px solid var(--line);background:#fff}
.sf-logo{height:30px;width:auto}
.sf-nav{display:flex;gap:20px;font-size:13.5px;font-weight:600;color:var(--muted);flex-wrap:wrap}
.sf-nav .on{color:var(--purple);position:relative}
.sf-nav .on::after{content:"";position:absolute;left:0;right:0;bottom:-15px;height:2px;background:var(--purple)}
.sf-body{padding:var(--space-4);background:#fbfafd}
@media(min-width:768px){.sf-body{padding:var(--space-5)}}
.sf-lead{display:flex;gap:18px;align-items:flex-start;margin-bottom:4px}
.sf-lead .sf-img{height:148px;width:228px;flex-shrink:0;margin:0}
.sf-lead .sf-lines{flex:1;min-width:0;padding-top:4px}
.sf-img{background:linear-gradient(135deg,var(--neutral-soft),var(--neutral-line));border-radius:12px}
.sf-lines i{display:block;height:11px;border-radius:6px;background:#e9e6f0;margin-bottom:9px}
.sf-row{display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-top:22px}
.sf-art{display:flex;gap:14px;align-items:flex-start}
.sf-art .sf-img{height:74px;width:108px;flex-shrink:0;margin:0}
.sf-art .sf-lines{flex:1;min-width:0}

/* the embed itself — a full-width "Upcoming Events" band that matches the paper's full-width layout (no sidebar) */
.embed-wrap{position:relative;margin:24px 0}
.embed-note{position:absolute;top:-12px;right:14px;z-index:2;font-size:11px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:#fff;background:var(--gold);padding:4px 10px;border-radius:7px;box-shadow:var(--shadow)}
.teaser-widget{border:2px solid var(--purple);border-radius:var(--r-md);overflow:hidden;box-shadow:var(--shadow-lg);background:#fff}
.tw-head{display:flex;align-items:center;justify-content:space-between;gap:12px;background:var(--purple);color:#fff;padding:12px 16px}
.tw-head>span{font-family:var(--serif);font-weight:700;font-size:17px}
.tw-all{font-size:13px;font-weight:700;color:#fff;white-space:nowrap;opacity:.95}
.tw-all:hover{opacity:1;text-decoration:underline}
.tw-strip{display:grid;grid-template-columns:repeat(auto-fit,minmax(168px,1fr));gap:10px;padding:14px}
.tw-card{display:block;border:1px solid var(--line);border-radius:11px;padding:12px 13px;text-decoration:none;background:#fff;transition:border-color var(--t) ease,box-shadow var(--t) ease,background var(--t) ease}
.tw-card:hover{border-color:var(--purple);background:var(--purple-wash);box-shadow:var(--shadow)}
.tw-d{font-size:11px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--purple);margin-bottom:6px}
.tw-t{font-weight:700;font-size:13.5px;color:var(--ink);line-height:1.3;margin-bottom:5px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.tw-m{font-size:12px;color:var(--muted)}

.how{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--space-5);margin:var(--space-6) 0 var(--space-2)}
.how-step{display:flex;gap:var(--space-3);align-items:flex-start}
.how-n{flex-shrink:0;width:32px;height:32px;border-radius:50%;background:var(--purple);color:#fff;font-weight:800;font-size:15px;display:flex;align-items:center;justify-content:center;font-family:var(--serif)}
.how-step h4{font-family:var(--serif);font-weight:700;font-size:16px;margin:3px 0 5px;line-height:1.18}
.how-step p{margin:0;font-size:13.5px;color:var(--body);line-height:1.5}
.teaser-cta{text-align:center;margin:var(--space-6) 0 var(--space-2)}

@media(max-width:820px){
  .props{grid-template-columns:1fr}
  .rev-grid{grid-template-columns:1fr 1fr}
  .how{grid-template-columns:1fr;gap:var(--space-6)}
}

/* ---------- Responsive tiers (1024 / 760 / 540 / 480 / 400) ---------- */
/* The gutter tiers live at the top of the sheet (16 base / 12 at <=400 / 24 at
   >=768). A .wrap{padding:0 22px} used to sit in this tier and, being later in
   the sheet, silently overrode all three below 1024px -- every phone got 22
   and nobody had chosen it (Mark, 8/26: "the margins on the left and right of
   all the cards and the whole feed"). Removed; the designed tiers apply. */
@media(max-width:1024px){.revenue{padding-top:var(--space-7)}.rev-grid{gap:12px}}

@media(max-width:760px){
  .catselect{margin-left:0;flex-basis:100%;margin-top:4px}
  .catselect select{width:100%}
}

@media(max-width:540px){
  :root{--header-h:56px}
  .site-header .wrap{gap:8px}
  .header-actions{gap:8px}
  .btn-sm{padding:7px 10px;font-size:12.5px}
  .chip-div{display:none}
  .spotlight{min-height:200px}
  .spotlight .meta{gap:6px 12px;font-size:13.5px;margin-bottom:12px}
  .spotlight h2{font-size:21px}
  .adslot{flex-wrap:wrap;gap:12px}
  .adslot .ico{width:40px;height:40px;border-radius:var(--r-sm)}
  .adslot .cta{order:3;flex-basis:100%;text-align:center;min-height:44px;display:inline-flex;align-items:center;justify-content:center}
  .sf-body{padding:var(--space-4)}
  .sf-lead{flex-direction:column;gap:10px}
  .sf-lead .sf-img{width:100%;height:150px}
  .sf-row{grid-template-columns:1fr;gap:16px}
  .sf-art .sf-img{width:96px;height:66px}
  .sf-nav{gap:14px;font-size:12.5px}
  .cover-hero h1 br{display:none}
}

@media(max-width:480px){
  .two{grid-template-columns:1fr}
  .grid{grid-template-columns:1fr}
  .mactions{flex-direction:column}
  .mactions .btn{width:100%;justify-content:center}
  .rev-grid{grid-template-columns:1fr;gap:var(--space-3)}
  .rev-item{padding:var(--space-4)}
  .paynote{padding:20px 20px}
  .header-actions .btn-ghost{display:none}  /* logo already links to index.html; keeps Submit uncramped */
}

@media(max-width:400px){
  .evcard{gap:10px;padding:10px}
  .evcard .thumb{width:72px;height:72px;border-radius:9px}
  .evcard h3{font-size:17px}
  .evcard .where{font-size:13px;margin-bottom:6px}
  #map{height:380px}
  .spotlight .meta{flex-direction:column;gap:5px}
  .sf-bar{padding:12px 14px;gap:12px}
  .sf-nav{display:none}   /* faux nav is decorative; kills horizontal overflow at 320–375 */
}

/* MOVED: the iOS zoom guard now lives at the END of this file. A bare
   element selector here was outranked by every later class rule (.mmform's
   15px, for one), so the guard silently failed on the surfaces that had
   their own styling. Keep-last is load-bearing, not a preference. */

/* ---------- Mobile top-bar polish (pass 2): calm, crisp first impression ---------- */
.demobar .db-short{display:none}
@media(max-width:600px){
  /* one tidy banner line instead of a 3-line wrap */
  .demobar{font-size:12px;padding:calc(9px + var(--safe-top)) 14px 9px;line-height:1.4}
  .demobar .db-full{display:none}
  .demobar .db-short{display:inline}
  /* lighter header: smaller logo, drop the divider + the redundant state pill
     (the gold banner + header tint + breadcrumb already say "live demo") */
  .brand img{height:26px}
  .brand .sep{display:none}
  .statepill{display:none}
  .site-header .wrap{gap:10px}
  /* kill the third "live demo" shout — the banner already carries it */
  .state-demo .eyebrow-live{display:none}
  /* tighten the run-up to the calendar */
  .crumb{padding-top:10px;font-size:12px}
  .state-demo .hero{padding-top:var(--space-4)}
  /* live papers: the masthead already names the paper — the hero is a dateline,
     not a pitch, so the calendar starts inside the first screen. Anytown keeps
     the tall hero: it is selling. The H1 wraps, never truncates. */
  .state-live .hero{padding:var(--space-3) 0 var(--space-2)}
  .state-live .hero h1{font-size:22px}
  .state-live .hero p{display:none}
}

/* ---------- Mobile container / overflow fixes (pass 2.1) ---------- */
@media(max-width:600px){
  html{overflow-x:clip}                          /* belt: never let a phone scroll sideways */
  .teaser-widget,.siteframe,.sf-body,.tw-strip{max-width:100%;min-width:0}
  .sf-body{padding:14px}                          /* a little breathing room around the embedded widget */
}

/* ============ Pitch surfaces (overview + teaser): editorial neutral, purple = "go live" only ============ */
/* calm neutral state banner instead of full purple */
.state-overview .demobar,.state-teaser .demobar{background:#f0eef4;color:var(--ink);border-bottom:1px solid var(--line)}
.state-overview .demobar b,.state-teaser .demobar b{color:var(--ink)}
/* status pill -> neutral (it's a label, not an action) */
.state-overview .statepill,.state-teaser .statepill{background:#ecebf1;color:var(--muted);border:1px solid var(--line)}
/* hero wordmark -> ink, matching her real black masthead */
.state-overview .cover-hero h1 .accent,.state-teaser .cover-hero h1 .accent{color:var(--ink)}
/* eyebrow -> calm neutral */
.state-overview .eyebrow,.state-teaser .eyebrow{background:#ecebf1;color:var(--muted)}
/* prop icons -> neutral slate (the gold "money" icon stays gold on purpose) */
.state-overview .ic-purple{background:#ecebf1;color:#574f6d}
/* revenue labels -> ink, neutral card wash */
.state-overview .rev-tag{color:var(--ink)}
.state-overview .rev-item{background:linear-gradient(180deg,#fff,#f5f4f8);border-color:var(--line)}
/* numbered steps (teaser) -> neutral */
.state-teaser .how-n{background:#574f6d}
/* closing band -> dark slate (drops the big purple block, and its CTA finally reads) */
.state-overview .whatsnext{background:linear-gradient(120deg,#272430,#3a3644)}
/* make the white CTA actually render anywhere (was only styled inside .donateband) */
.btn-white{background:#fff;color:var(--purple)}
.btn-white:hover{background:color-mix(in srgb,var(--accent) 8%,#fff)}

/* ---------- Compact sticky toolbar on phones (reclaim viewport for content) ---------- */
.datechips{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
@media(max-width:600px){
  /* date pills = one swipeable row instead of wrapping to two; category drops below */
  #chiprow{align-items:stretch}
  .datechips{flex:0 0 100%;flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none;padding-bottom:2px}
  .datechips::-webkit-scrollbar{display:none}
  .datechips .chip{flex:0 0 auto}
  .catselect{flex:0 0 100%;margin-left:0;margin-top:0}
  .catselect select{width:100%}
  /* trim the bar's height */
  .toolbar{padding:10px 0}
  .searchrow{margin-bottom:8px}
  .search input{height:44px}
  .search svg{top:13px}
  .resultcount{margin:10px 2px 2px}
}

/* ---------- Mobile readability bump (S5: nothing meaningful shrinks below ~11px) ---------- */
@media(max-width:600px){
  .cat,.free,.cost,.sponsor{font-size:12px}
  .evcard .where,.tile .where,.resultcount{font-size:13.5px}
  .statepill{font-size:12px}
  .spotlight .tag{font-size:12px}
  .crumb{font-size:13px}
}

/* ---------- Leaflet OSM attribution: legible + non-tiny (m6) ---------- */
.leaflet-control-attribution a{color:#0a5a7a}
.leaflet-control-attribution{font-size:11px}

/* ---------- Long line length on wide screens (m9) ---------- */
.prop p,.adslot p,.how-step p{max-width:60ch}

/* ---------- Reduced motion: also calm hover/tap transforms + modal pop (m7) ---------- */
@media(prefers-reduced-motion:reduce){
  .evcard:hover,.tile:hover{transform:none}
  .btn:active,.chip:active,.viewtoggle button:active{transform:none}
  .modal{animation:none}
  *{transition-duration:0.001ms !important}
}

/* ---------- Ad-slot sample thumbnail (lets her picture an advertiser's graphic in context) ---------- */
.adslot .adthumb{position:relative;flex-shrink:0;width:108px;height:80px;border-radius:9px;overflow:hidden;color:#fff;
  background:linear-gradient(135deg,#2f6f9e,#57a0cf);display:flex;flex-direction:column;justify-content:flex-end;padding:9px 10px;box-shadow:inset 0 0 0 1px rgba(0,0,0,.07)}
.adslot .adthumb-tag{position:absolute;top:6px;left:6px;font-size:9px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;background:rgba(255,255,255,.92);color:#26506e;padding:2px 6px;border-radius:5px}
.adslot .adthumb-logo{position:absolute;top:7px;right:8px;width:22px;height:22px;border-radius:6px;background:rgba(255,255,255,.92);color:#2f6f9e;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:800}
.adslot .adthumb-copy b{display:block;font-family:var(--serif);font-size:15px;line-height:1.05}
.adslot .adthumb-copy span{font-size:10.5px;opacity:.95}
@media(max-width:540px){.adslot .adthumb{width:90px;height:74px}.adslot .adthumb-copy b{font-size:13px}}

/* ---------- Scroll-condensing sticky chrome (ALL tenants, phones + small
   tablets): reclaim viewport while reading. Demo and live share ONE condense
   contract — app.js toggles body.condensed for every tenant and
   scrollToResults measures against the 48px condensed header, so these rules
   must never be state-gated (a state-live body without them overshoots every
   filter-tap scroll and buries results under the toolbar). ---------- */
@media(max-width:768px){
  /* body:not(.admin): admin.html loads this sheet too and shares .brand — an
     unscoped height transition there makes the sticky admin masthead jitter
     on every scroll frame (Mark's phone, 7/30). The reader states share ONE
     contract; the admin simply isn't party to it. */
  body:not(.admin) .site-header .wrap{transition:height .18s ease}
  body:not(.admin) .brand img{transition:height .18s ease}
  body:not(.admin) #chiprow{max-height:140px;overflow:hidden;transition:max-height .22s ease,opacity .18s ease,margin .2s ease}
  body:not(.admin).condensed .site-header .wrap{height:44px}
  /* the brand is a TEXT span (boot.js writes textContent) — the old img rule
     matched nothing, which is why condensing looked dead; shrink the type */
  body:not(.admin).condensed .brand-name{font-size:16px}
  /* keep the safe-area term: dropping it slid the toolbar under the iOS
     status bar in the installed app the moment the header condensed */
  body:not(.admin).condensed .toolbar{top:calc(44px + var(--safe-top))}
  body:not(.admin).condensed #chiprow{max-height:0;opacity:0;margin:0;pointer-events:none}
  body:not(.admin) .toolbar:focus-within #chiprow{max-height:140px;opacity:1;pointer-events:auto}
  /* on a filter tap, results snap to just under the condensed bar (see scrollToResults) */
  #resultcount{scroll-margin-top:calc(var(--dayhead-top) + 8px)}
}

/* more air above the eyebrow on phones so it doesn't read as bolted to the header */
@media(max-width:600px){.cover-hero{padding-top:64px}}

/* ---------- Install prompt (banner + info sheet) + app-share ---------- */
.install-banner{position:fixed;left:12px;right:12px;bottom:calc(12px + var(--safe-bottom));z-index:180;display:flex;align-items:center;gap:14px;flex-wrap:wrap;background:#fff;border:1px solid var(--line);border-radius:16px;box-shadow:0 12px 34px rgba(28,23,38,.20);padding:14px 16px;max-width:560px;margin:0 auto;transform:translateY(160%);opacity:0;transition:transform .32s cubic-bezier(.2,.7,.2,1),opacity .3s ease}
.install-banner.show{transform:none;opacity:1}
.install-banner .ib-txt{flex:1 1 200px;min-width:0;display:flex;flex-direction:column;gap:2px}
.install-banner .ib-txt b{font-size:15px;color:var(--ink)}
.install-banner .ib-txt span{font-size:13px;color:var(--muted);line-height:1.4}
.install-banner .ib-act{display:flex;gap:8px;align-items:center;flex-shrink:0}
@media(max-width:420px){.install-banner .ib-act{flex-basis:100%}.install-banner .ib-add{flex:1;justify-content:center}}
@media(prefers-reduced-motion:reduce){.install-banner{transition:opacity .2s ease;transform:none}}
.ins-back{position:fixed;inset:0;z-index:190;background:rgba(28,23,38,.5);display:flex;align-items:flex-end;justify-content:center;opacity:0;transition:opacity .2s ease}
.ins-back.open{opacity:1}
.ins-sheet{position:relative;background:#fff;width:100%;max-width:520px;max-height:90vh;overflow:auto;border-radius:20px 20px 0 0;padding:26px 22px calc(26px + var(--safe-bottom));box-shadow:0 -10px 34px rgba(28,23,38,.28);transform:translateY(24px);transition:transform .25s ease}
.ins-back.open .ins-sheet{transform:none}
@media(min-width:560px){.ins-back{align-items:center}.ins-sheet{border-radius:18px;max-height:86vh}}
@media(prefers-reduced-motion:reduce){.ins-back,.ins-sheet{transition:opacity .2s ease}.ins-sheet{transform:none}}
.ins-x{position:absolute;top:12px;right:12px;width:34px;height:34px;border:0;background:var(--bg);border-radius:50%;font-size:22px;line-height:32px;color:var(--muted);cursor:pointer;padding:0}
.ins-x:hover{background:var(--line);color:var(--ink)}
.ins-sheet h2{font-family:var(--serif);font-weight:800;font-size:22px;margin:0 30px 12px 0;line-height:1.16;color:var(--ink)}
.ins-sheet h3{font-size:13px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--purple);margin:20px 0 9px}
.ins-intro{font-size:14.5px;line-height:1.55;color:var(--body);margin:0 0 10px}
.ins-sub{font-size:13px;font-weight:700;color:var(--ink);margin:14px 0 6px}
.ins-steps{margin:0;padding-left:22px;display:flex;flex-direction:column;gap:9px}
.ins-steps li{font-size:14.5px;line-height:1.5;color:var(--ink)}
.ins-fine{background:var(--bg);border:1px solid var(--line);border-radius:12px;padding:13px 15px;margin:18px 0 0}
.ins-fine p{font-size:13px;color:var(--muted);line-height:1.5;margin:0 0 8px}
.ins-fine p:last-child{margin:0}
.ins-push{font-size:13.5px;line-height:1.5;color:var(--purple-dark);background:var(--purple-wash);border:1px solid var(--purple-line);border-radius:12px;padding:12px 15px;margin:16px 0 0}
.app-share{text-align:center;margin:var(--space-5) 0 var(--space-2)}
.app-share .as-lead{font-size:15px;color:var(--muted);margin:0 0 13px}
.footrow{margin:12px 0 0}
/* Utility links are chrome. Once the band went ink they were, by count, the most
   accent on the screen (design panel, 8/28). Neutral ink; the accent returns on press. */
.footlink{background:none;border:0;padding:0;font:inherit;font-size:13px;font-weight:600;color:var(--neutral-ink);cursor:pointer;display:inline-flex;align-items:center;gap:6px;min-height:44px}
.footlink svg{color:var(--muted);width:14px;height:14px;flex-shrink:0}
.footlink:hover,.footlink:active,.footlink:focus-visible{color:var(--purple);text-decoration:underline;text-underline-offset:2px}
.fl-short{display:none}
@media(max-width:600px){.footsep{display:none}.footrow{gap:6px 20px}}
/* Three links on one line at 390: the long label yields its words, like the masthead's Submit. */
@media(max-width:480px){.fl-long{display:none}.fl-short{display:inline}}

/* ---- text wordmark (product: tenant brand is text, not a logo file) ---- */
.brand-name{font-family:var(--serif);font-weight:800;font-size:19px;color:var(--ink);letter-spacing:.01em;white-space:nowrap}   /* ink: the nameplate is authority; the hero city word is the brand moment */

/* Imageless events: designed category-glyph card, never a missing image */
/* ---------- Imageless tiles: the product's actual face ---------------------
   Nine of ten community-calendar events arrive without art, so this tile is
   what the feed mostly IS. Color and texture key off the event's TOPIC (the
   same resolution that picks the glyph), which turns a wall of one lavender
   into something scannable — sage is wellness, slate is government. NOT the
   paper's accent: that is exactly what made every card purple. Tints stay
   pale and inks muted so a tile reads as a printed section marker, never as
   candy and never as a photograph, because it isn't one. Textures are CSS
   gradients: no requests, no bytes, offline-safe, and they stay distinct in
   grayscale.

   STRUCTURE MATTERS HERE: every variation is a custom property set at ONE
   class (.noimg / .noimg.t-x), while the painting happens at three classes
   (.tile .pic.noimg) so it outranks .tile .pic's own background. Flip that
   and the topic tints lose the cascade silently — which is exactly what
   happened on the first attempt. ---------- */
.noimg{
  --tint:#efedf3;--tint2:#e5e2ec;--ink:#5f586e;
  --pat:radial-gradient(currentColor .9px,transparent 1px);--pat-size:13px 13px;--pat-op:.14}

/* topic palette — muted, ink-leaning, print-shop rather than web-app */
.noimg.t-books {--tint:#f6efdf;--tint2:#efe4cd;--ink:#7d5b28}
.noimg.t-family{--tint:#fdefe0;--tint2:#f8e2cb;--ink:#a35f2b}
.noimg.t-people{--tint:#f8f0dd;--tint2:#f1e5c7;--ink:#85662a}
.noimg.t-food  {--tint:#faeae0;--tint2:#f4dbcb;--ink:#96502f}
.noimg.t-craft {--tint:#f7eae6;--tint2:#f0d9d3;--ink:#92503f}
.noimg.t-game  {--tint:#eeeaf7;--tint2:#e0daef;--ink:#5b4b8a}
.noimg.t-clock {--tint:#f1ebe3;--tint2:#e7ded1;--ink:#6f5d47}
/* ruled paper — civic and screening-room topics */
.noimg.t-gov,.noimg.t-movie,.noimg.t-biz{
  --pat:repeating-linear-gradient(90deg,currentColor 0 1px,transparent 1px 11px);--pat-size:auto;--pat-op:.11}
.noimg.t-gov   {--tint:#e8edf4;--tint2:#d8e0ec;--ink:#43536e}
.noimg.t-movie {--tint:#eaebf6;--tint2:#dadcee;--ink:#4c4f80}
.noimg.t-biz   {--tint:#eaeef2;--tint2:#dae1e8;--ink:#4a5866}
/* graph paper — the measured, clinical topics */
.noimg.t-heart,.noimg.t-tech{
  --pat:repeating-linear-gradient(0deg,currentColor 0 1px,transparent 1px 14px),repeating-linear-gradient(90deg,currentColor 0 1px,transparent 1px 14px);
  --pat-size:auto;--pat-op:.09}
.noimg.t-heart {--tint:#e8f1ea;--tint2:#d8e7dc;--ink:#3e6b4e}
.noimg.t-tech  {--tint:#e6f0f4;--tint2:#d5e5eb;--ink:#3a6274}
/* hatching — things that happen outside or in motion */
.noimg.t-leaf,.noimg.t-yoga,.noimg.t-ball,.noimg.t-music{
  --pat:repeating-linear-gradient(45deg,currentColor 0 1px,transparent 1px 10px);--pat-size:auto;--pat-op:.11}
.noimg.t-leaf  {--tint:#e9f2e5;--tint2:#d9e9d3;--ink:#46683c}
.noimg.t-yoga  {--tint:#e7f2f0;--tint2:#d6e8e5;--ink:#3d6a63}
.noimg.t-ball  {--tint:#e9f2e7;--tint2:#d9e8d5;--ink:#4a6b41}
.noimg.t-music {--tint:#fbeae6;--tint2:#f5d9d3;--ink:#a1453a}

/* the painting — three classes so it beats .tile .pic / .evcard .thumb */
.evcard .thumb.noimg,.tile .pic.noimg,.modal .hero-glyph.noimg,.admin .ev-thumb.noimg{
  position:relative;overflow:hidden;display:flex;align-items:center;justify-content:center;
  color:var(--ink);background:linear-gradient(150deg,var(--tint),var(--tint2))}
.evcard .thumb.noimg::before,.tile .pic.noimg::before,.modal .hero-glyph.noimg::before,.admin .ev-thumb.noimg::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background-image:var(--pat);background-size:var(--pat-size);opacity:var(--pat-op)}
.evcard .thumb.noimg svg,.tile .pic.noimg svg,.modal .hero-glyph.noimg svg,.admin .ev-thumb.noimg svg{position:relative}
.evcard .thumb.noimg svg{width:38px;height:38px}
.tile .pic.noimg svg{width:58px;height:58px}
@media(max-width:700px){.evcard .thumb.noimg svg{width:32px;height:32px}}
@media(max-width:400px){.evcard .thumb.noimg svg{width:28px;height:28px}}
/* Detail modal: quieter glyph hero for imageless events — same language, no zoom */
.modal .hero-glyph{height:172px;display:flex;align-items:center;justify-content:center}
.modal .hero-glyph svg{width:76px;height:76px;stroke-width:1.6}
@media(max-width:560px){.modal .hero-glyph{height:136px}.modal .hero-glyph svg{width:62px;height:62px}}

/* All-view horizon fold */
.fold-row{display:flex;justify-content:center;padding:26px 0 10px}
.fold-row .btn{min-width:min(340px,80vw)}
.empty-doors{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;margin-top:16px}

/* ---- money surfaces (Ad Center P1) ---- */
.mmodal{position:fixed;inset:0;background:rgba(18,10,28,.55);display:flex;align-items:center;justify-content:center;z-index:120;padding:18px}
.mmcard{position:relative;background:#fff;border-radius:16px;box-shadow:0 24px 70px rgba(28,23,38,.35);max-width:440px;width:100%;padding:26px 24px 22px;max-height:88vh;overflow:auto}
.mmcard h3{font-family:var(--serif);font-size:22px;margin:0 34px 8px 0}
.mmclose{position:absolute;top:12px;right:12px;width:34px;height:34px;border-radius:50%;border:1px solid var(--purple-line);background:#fff;color:var(--ink);display:flex;align-items:center;justify-content:center;cursor:pointer}
.mmclose svg{width:16px;height:16px}
.mmsub{font-size:14px;line-height:1.55;color:#4a4358;margin:0 0 12px}
.mmchips{display:flex;gap:8px;flex-wrap:wrap;margin:6px 0 12px}
.mmchip{border:1.5px solid var(--purple-line);background:#fff;border-radius:999px;padding:9px 18px;font-size:15px;font-weight:700;cursor:pointer;color:var(--ink)}
.mmchip.on{background:var(--purple);border-color:var(--purple);color:#fff}
.mmcustom{width:90px;border:1.5px solid var(--purple-line);border-radius:999px;padding:9px 14px;font-size:15px;font-weight:700}
.mmmonthly{display:flex;align-items:center;gap:8px;font-size:14px;margin:0 0 14px;color:#4a4358}
.mmgo{width:100%}
.mmfine{font-size:12px;color:var(--muted);margin:10px 0 0;text-align:center}
.mmform label{display:block;font-size:13px;font-weight:600;margin:0 0 10px;color:#3a3349}
.mmform input,.mmform textarea{display:block;width:100%;margin-top:5px;border:1.5px solid var(--purple-line);border-radius:10px;padding:10px 12px;font-size:15px;font-family:inherit}
.mmform button[type=submit]{width:100%;margin-top:4px}
.sponsorband .sp-logo{width:58px;height:58px;border-radius:11px;object-fit:contain;background:#fff;flex-shrink:0;border:1px solid var(--gold-line)}
@media(max-width:680px){.sponsorband .sp-logo{width:64px;height:64px}
  .sponsorband .sp-name{font-size:22px}}
.thanksbar{position:fixed;left:50%;top:calc(var(--header-h) + 10px);transform:translate(-50%,-220%);background:var(--ink);color:#fff;font-size:14px;font-weight:600;line-height:1.4;padding:13px 17px;border-radius:14px;box-shadow:0 10px 30px rgba(28,23,38,.35);z-index:210;display:flex;align-items:flex-start;gap:10px;transition:transform .35s ease;width:max-content;max-width:min(520px,92vw);text-align:left}
.thanksbar.in{transform:translate(-50%,0)}
.thanksbar svg{width:16px;height:16px;flex-shrink:0;margin-top:2px}
@media(prefers-reduced-motion:reduce){.thanksbar{transition:none}}

.footrow{display:flex;align-items:center;justify-content:center;gap:10px;flex-wrap:wrap}
.footsep{color:var(--muted);opacity:.6}
a.footlink{text-decoration:none;display:inline-flex;align-items:center;gap:6px}
.mactions .btn svg{width:15px;height:15px;flex-shrink:0}

/* moderator mode (admin session on this origin) */
.mod-pill{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:800;color:var(--purple);background:var(--purple-wash);border:1px solid var(--purple-line);border-radius:999px;padding:6px 12px;text-decoration:none;margin-left:10px}
.mod-pill svg{width:13px;height:13px}
.modbar{display:flex;flex-direction:column;gap:9px;background:linear-gradient(135deg,var(--purple-wash),#fff 70%);border:1px solid var(--purple-line);border-radius:12px;padding:11px 12px;margin:18px 0 2px}
.modbar-lab{display:inline-flex;align-items:center;gap:5px;font-size:10.5px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--purple)}
.modbar-lab svg{width:12px;height:12px}
.modbar-acts{display:grid;
  /* 140 not 96: at 390px this yields two 179px buttons and every label --
     including "Edit in the Desk" at 113px -- sits on one line. 96px gave
     three 117px tracks that the labels spilled out of. min(100%,...) keeps a
     track from ever exceeding a narrow container. Measured, not guessed. */
  grid-template-columns:repeat(auto-fit,minmax(min(100%,140px),1fr));gap:7px}
.mod-act{font:inherit;font-size:13px;font-weight:700;color:var(--ink);background:#fff;border:1px solid var(--purple-line);border-radius:9px;padding:9px 10px;cursor:pointer;text-decoration:none;text-align:center;min-width:0;
  /* Was white-space:nowrap against a minmax(96px,...) track: "Edit in the
     Desk" is ~140px at 13px/700, so the label spilled its button (Mark, 8/3).
     Wrap instead, and min(100%,112px) keeps a track from ever exceeding the
     container at 390px. */
  white-space:normal;line-height:1.25;overflow-wrap:break-word;hyphens:auto}
.mod-act:hover{background:var(--purple-wash)}
.mod-act.danger{color:#b3261e;border-color:#e7c4c0}
.mod-act[disabled]{opacity:.5}

/* Moderator pill lives in a header built for two items — keep the masthead
   whole: shrink to a lock-only chip on phones, never let it push the brand. */
.mod-pill{flex-shrink:0}
/* Phone header budget: the masthead is the paper's name — it never truncates.
   The action buttons give up their long labels instead. */
.sub-short{display:none}
@media(max-width:700px){
  .sub-long{display:none}
  .sub-short{display:inline}
  .site-header .btn-sm{padding:8px 12px}
}
.site-header .brand{min-width:0;flex:1 1 auto}
.site-header .brand-name{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.header-actions{flex-shrink:0}
@media(max-width:700px){
  .mod-pill{margin-left:6px;padding:6px 9px;gap:0}
  .mod-pill .mp-label{display:none}
}
@media(max-width:430px){
  .site-header .brand,.site-header h1{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
}
/* The source's own page: tickets for paid events, details for the rest.
   Full-width above the action row — it's the reader's most likely next step. */
.srclink{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;margin:16px 0 0}
.srclink svg{width:15px;height:15px;flex-shrink:0}
.srchost{font-weight:600;opacity:.72;font-size:12.5px}
@media(max-width:430px){.srchost{display:none}}
/* Series: a run states its own cadence; a recurring program admits it recurs */
.spanline{font-weight:800;letter-spacing:.01em}
.cadence{font-size:12px;color:var(--muted);font-weight:600;margin-top:3px}
.tag-run{background:var(--purple-wash);color:var(--purple);border:1px solid var(--purple-line)}
/* A bought placement says so, in the badge row the card already has. Gold ties
   it to the sponsor band; --gold-text is the AA-safe gold-as-text token. */
.tag-spon{background:var(--gold-soft);color:var(--gold-text);border:1px solid var(--gold-line);font-weight:800;letter-spacing:.03em}
/* The series lives in the modal: every date one tap away */
.mseries{background:var(--purple-wash);border:1px solid var(--purple-line);border-radius:12px;padding:12px 13px;margin:16px 0 2px}
.ms-head{font-size:13.5px;color:var(--purple-dark);display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin-bottom:9px}
.ms-head svg{width:14px;height:14px;flex-shrink:0}
.ms-dates{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px}
.ms-chip{font:inherit;font-size:12.5px;font-weight:700;color:var(--ink);background:#fff;border:1px solid var(--purple-line);border-radius:999px;padding:6px 11px;cursor:pointer;display:inline-flex;align-items:center;gap:6px}
.ms-chip.on{background:var(--purple);border-color:var(--purple);color:#fff}
.ms-chip .ms-t{font-weight:600;opacity:.7;font-size:11.5px}
.ms-more{font-size:12px;color:var(--muted);align-self:center}
/* Year banner inside a series chip row. flex-basis:100% forces a line break so
   the year heads the chips that follow it instead of floating between two. */
.ms-yr{flex:0 0 100%;font-size:11px;font-weight:800;letter-spacing:.08em;color:var(--muted);margin-top:4px}
.ms-all{font:inherit;font-size:13px;font-weight:700;color:var(--purple);background:#fff;border:1px solid var(--purple-line);border-radius:9px;padding:9px 12px;width:100%;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:7px}
.ms-all svg{width:14px;height:14px}

/* Ongoing programs: on every day, so they belong to none of them */
.ongoing{background:linear-gradient(135deg,var(--purple-wash),#fff 72%);border:1px solid var(--purple-line);border-radius:14px;padding:12px 14px;margin:0 0 18px}
.og-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:11.5px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--purple);margin-bottom:8px}
.og-head svg{width:14px;height:14px}
.og-sub{font-weight:600;letter-spacing:0;text-transform:none;color:var(--muted);font-size:12px}
.og-row{display:flex;flex-direction:column;gap:2px;width:100%;text-align:left;background:#fff;border:1px solid var(--purple-line);border-radius:10px;padding:10px 12px;margin-top:7px;cursor:pointer;font:inherit}
.og-row:first-of-type{margin-top:0}
.og-row:hover{border-color:var(--purple)}
.og-name{font-family:var(--serif);font-weight:700;font-size:15px;color:var(--ink);line-height:1.25}
.og-meta{font-size:12.5px;color:var(--muted);font-weight:600}
.ms-count{color:var(--muted);font-weight:600}

/* Ongoing + series blocks: structure gray, accent only on the actionable bits */
.ongoing{background:linear-gradient(135deg,var(--neutral-soft),#fff 72%);border-color:var(--neutral-line)}
.og-head{color:var(--neutral-ink)}
.og-row{border-color:var(--neutral-line)}
.mseries{background:var(--neutral-soft);border-color:var(--neutral-line)}
.ms-head{color:var(--neutral-ink)}
.ms-chip{border-color:var(--neutral-line)}
.tag-run{background:var(--neutral-soft);color:var(--neutral-ink);border-color:var(--neutral-line)}


/* Installed PWA: with no browser chrome the document starts at y=0, under the
   status bar and the notch — the masthead, Submit and the Admin pill were all
   physically untappable. Pad the header by the safe-area inset and give the
   sticky offsets the same treatment. */
/* Safe-area insets, UNCONDITIONAL — see the note above about display-mode.
   The masthead drew under the status bar and an open modal's close button hid
   behind it (Mark, 8/1) because these lived inside a media query that had
   stopped matching. env() is 0 where chrome already offsets the page. */
.site-header{padding-top:var(--safe-top)}
/* no bare wrap-height re-set here: this unconditional block loads AFTER the
   condense rules and silently pinned the header at full height on phones —
   the reason task #10's "masthead never shrinks" existed. The base height
   already lives at the top of the sheet. */
.toolbar{top:calc(var(--header-h) + var(--safe-top))}
.thanksbar{top:calc(var(--header-h) + var(--safe-top) + 10px)}

/* An element told to hide must hide: .spotlight's display rule was beating the
   hidden attribute, leaving an empty dark rectangle where a hero would be. */
[hidden]{display:none !important}

/* Pull to refresh (installed app has no reload button) */
.ptr{position:fixed;top:calc(var(--safe-top) + 6px);left:50%;transform:translate(-50%,0);opacity:0;
  width:34px;height:34px;border-radius:50%;background:#fff;border:1px solid var(--line);
  box-shadow:0 4px 14px rgba(28,23,38,.14);display:flex;align-items:center;justify-content:center;
  z-index:180;pointer-events:none;transition:transform .18s ease,opacity .18s ease}
.ptr-spin{width:15px;height:15px;border-radius:50%;border:2px solid var(--neutral-line);border-top-color:var(--purple);transition:transform .2s ease}
.ptr.ready .ptr-spin{transform:rotate(180deg)}
.ptr.go .ptr-spin{animation:ptrspin .7s linear infinite}
@keyframes ptrspin{to{transform:rotate(360deg)}}
@media(prefers-reduced-motion:reduce){.ptr,.ptr-spin{transition:none}.ptr.go .ptr-spin{animation:none}}
.map-empty{background:var(--neutral-soft);border:1px dashed var(--neutral-line);border-radius:12px;padding:16px 18px;margin-top:12px;font-size:14px;color:var(--muted);line-height:1.5}
.map-empty b{display:block;color:var(--ink);font-family:var(--serif);font-size:17px;margin-bottom:4px}



/* ---------- Mobile input floor (iOS zoom guard) — MUST BE LAST -------------
   iOS Safari force-zooms any focused control under 16px, and that zoom is
   what makes the whole viewport elastic afterward (Mark, 8/1: typing in the
   photo search threw the page sideways). The fix is a real 16px minimum, NOT
   maximum-scale/user-scalable — disabling pinch zoom to dodge this would
   break the page for anyone who needs to magnify it.
   !important because these controls are styled by CLASS everywhere (.mmform,
   .field, .wb-q, .set-in …) and any of those would otherwise outrank a bare
   element selector — the same specificity trap, one more time. ---------- */
@media(max-width:820px){
  input,textarea,select,
  .field input,.field textarea,.field select,
  .mmform input,.mmform textarea{font-size:16px !important}
}

/* Community-form poster preview: the submitter sees the actual photo they're
   sending (the native file control's mini-thumb is the OS's business and iOS
   often draws it black). Sized like the cards it will live in. */
.poster-add{align-self:flex-start}
.poster-prev{position:relative;margin-top:10px;border-radius:var(--r-sm);overflow:hidden;border:1px solid var(--line);max-width:420px}
.poster-prev img{display:block;width:100%;aspect-ratio:16/9;object-fit:cover}
.poster-remove{position:absolute;top:8px;right:8px;background:rgba(28,23,38,.78);color:#fff;border:0;border-radius:8px;padding:6px 11px;font-size:13px;font-weight:600;cursor:pointer}
.poster-remove:hover{background:rgba(28,23,38,.92)}

/* ---------- Signed-in whisper (thin-reader doctrine, refined 8/13) ----------
   State, not navigation: a non-link mark beside the masthead when a session
   is live. The neutral operator palette, whisper scale — a reader never sees
   it, and the operator stops wondering. */
/* The signed-in strip: a sentence, not an ornament. Non-sticky and in normal
   flow, so it scrolls away and never becomes operator furniture; it links
   nowhere. Replaced #editor-mark, which took its width from the paper's own
   masthead in violation of the header budget rule above, and whose only
   explanation was a title attribute iOS never renders (8/25). */
/* Full-bleed band, content on the SAME column as the masthead -- it reuses
   .wrap exactly like .site-header does. The first cut set max-width to a
   var(--maxw) that does not exist in this sheet, so the declaration was
   dropped and the sentence sat against the window edge while the paper's
   name sat at 1080px-centred (Mark, desktop PWA, 8/25). */
.sessionbar{padding:10px 0;background:var(--purple-wash);
  border-bottom:1px solid var(--purple-line);color:var(--neutral-ink)}
.sessionbar .sb-row{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.sessionbar .sb-txt{font-size:12.5px;line-height:1.45;min-width:0;flex:1 1 auto}
.sessionbar .sb-out{flex:none;display:inline-flex;align-items:center;justify-content:center;
  min-height:44px;padding:10px 14px;font:inherit;font-size:12.5px;font-weight:700;
  color:var(--purple-dark);background:#fff;border:1px solid var(--purple-line);
  border-radius:9px;cursor:pointer}
.sessionbar .sb-out:hover{background:var(--purple-wash)}
.sessionbar .sb-out[data-armed="1"]{border-color:var(--purple);color:var(--purple)}
/* When the sentence wraps to its own lines the button follows on the next
   row; keep it auto-width and right-aligned so it reads as the secondary
   thing it is. A full-width button here looked like the page's main action. */
.sessionbar .sb-out{margin-left:auto}
/* At-rest signal once the strip has scrolled away: the dot rides the action
   button, which is the flex child the header budget already designates as the
   one that yields -- so it costs the masthead nothing. */
.header-actions .mod-dot{width:6px;height:6px;border-radius:50%;background:#7ee2a8;
  flex:none;margin-right:2px}

/* The sanctioned in-context lane, extended to the feed: a pencil straight to
   the Desk editor, hover-revealed so the public layout is untouched even for
   the operator until she reaches for it. hover:hover keeps phones on their
   existing tap-into-modal flow. */
li{position:relative}
.ev-edit{display:none}
@media(hover:hover){
  .ev-edit{display:flex;align-items:center;justify-content:center;position:absolute;top:10px;right:10px;z-index:5;
    width:30px;height:30px;border-radius:50%;background:#fff;border:1px solid var(--neutral-line);
    color:var(--neutral-ink);box-shadow:0 2px 8px rgba(28,23,38,.14);opacity:0;transition:opacity .12s ease;
    pointer-events:none}
  li:hover .ev-edit,.ev-edit:focus-visible{opacity:1;pointer-events:auto}
  .ev-edit:hover{color:var(--purple);border-color:var(--purple)}
}

/* ---------- The long horizon (8/17): month picker + cliff-free timeline ---- */
.month-divider{display:flex;align-items:baseline;gap:10px;margin:26px 0 4px;padding:0 2px}
.month-divider span:first-child{font-family:var(--serif);font-weight:700;font-size:21px;color:var(--ink)}
.month-divider .md-n{font-size:13px;color:var(--muted)}
.terminus{text-align:center;color:var(--muted);font-size:13.5px;padding:26px 0 10px}
#tl-sentinel{height:2px}

/* Month sheet: same bones as the install sheet, rows sized for thumbs. */
.msheet-back{position:fixed;inset:0;z-index:220;background:rgba(28,23,38,.45);display:flex;align-items:flex-end;justify-content:center}
/* A sheet dismissed on pointerdown stays MOUNTED for the tail of the gesture so
   it swallows the pointerup and click instead of letting them reach the page
   beneath (dismissSheet() in app.js). Invisible, still full-screen, still
   hit-testable. Specificity is spelled out rather than left to source order --
   .ins-back.open also sets opacity. */
.ins-back.open.sheet-closing,.msheet-back.sheet-closing{opacity:0;pointer-events:auto}
@media(min-width:560px){.msheet-back{align-items:center}}
.msheet{padding-bottom:calc(14px + var(--safe-bottom))}
.msheet-row{display:flex;align-items:center;justify-content:space-between;width:100%;
  padding:14px 6px;border:0;border-bottom:1px solid var(--line);background:none;
  font:inherit;font-size:16px;font-weight:600;color:var(--ink);cursor:pointer;text-align:left}
.msheet-row:last-child{border-bottom:0}
.msheet-row:hover{color:var(--purple)}
.msheet-row.on{color:var(--purple)}
/* The selected row wears its state in the pill it already has. A dot here
   was a THIRD flex child, and space-between then shoved the count out of
   the column every other row keeps it in -- the one row you look at was the
   one that looked crooked (Mark, 8/17). */
.msheet-n{font-size:13px;font-weight:700;color:var(--muted);background:var(--neutral-soft);
  border-radius:999px;padding:3px 10px;flex:none}
.msheet-row.on .msheet-n{color:#fff;background:var(--purple)}

/* Cheap render for a long timeline: offscreen cards skip layout+paint. */
.evlist li{content-visibility:auto;contain-intrinsic-size:auto 132px}

/* ---------- /advertise: the buyer's view of the catalog (8/26) ----------
   Gold is the site's monetization grammar; this is the gold-grammar page. The
   band miniature reuses .sponsorband untouched so it can never drift from the
   real thing. */
/* Vertical only -- the shorthand's "0" for left/right was silently beating
   .wrap's gutter (same specificity, later in the sheet), so the hero ran
   edge-to-edge while every card below sat 22px in (Mark, 8/26). */
.adv-hero{padding-top:var(--space-7);padding-bottom:var(--space-5);text-align:center}
.adv-hero h1{font-family:var(--serif);font-weight:800;font-size:clamp(26px,4.4vw,40px);line-height:1.12;letter-spacing:-.015em;color:var(--ink);margin:0 0 10px}
.adv-hero h1 .accent{color:var(--purple)}
.adv-hero p{color:var(--body);font-size:clamp(15px,2.2vw,17px);max-width:34em;margin:0 auto}
.adv-col{max-width:760px;margin:0 auto}
.adv-cap{font-size:12px;font-weight:800;letter-spacing:.09em;text-transform:uppercase;color:var(--gold-text);margin:0 0 10px;display:flex;align-items:center;gap:8px}
.adv-cap::after{content:"";flex:1;height:1px;background:var(--gold-line)}
.adv-card{background:var(--card);border:1px solid var(--line);border-radius:var(--r-md);box-shadow:var(--shadow);padding:var(--space-5);margin-bottom:var(--space-5)}
.adv-card h2{font-family:var(--serif);font-weight:800;font-size:22px;line-height:1.15;margin:0;color:var(--ink)}
.adv-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:6px}
.adv-price{font-family:var(--serif);font-weight:800;font-size:20px;color:var(--gold-text);white-space:nowrap}
.adv-card p{color:var(--body);font-size:15px;line-height:1.5;margin:8px 0 0}
/* A pill (999px) may never wrap: half-of-height becomes a lozenge on line two.
   Short label + nowrap, or it isn't a pill and gets --r-sm instead. */
.adv-one{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;font-weight:700;color:var(--gold-text);background:var(--gold-soft);border:1px solid var(--gold-line);border-radius:999px;padding:4px 11px;margin-top:12px;white-space:nowrap}
.adv-avail{margin-top:14px;padding:12px 14px;border-radius:var(--r-sm);font-size:14px;line-height:1.45;background:var(--purple-wash);border:1px solid var(--purple-line);color:var(--ink)}
.adv-avail b{color:var(--purple)}
.adv-cta{margin-top:16px;display:flex;gap:10px;flex-wrap:wrap}
.adv-demo{margin:0 0 8px;pointer-events:none}
.adv-demo .sponsorband{margin-bottom:6px}
.adv-demo .cta{cursor:default}
.adv-demoline{font-size:12.5px;color:var(--faint);margin:0 0 var(--space-5);text-align:center}
.adv-steps{margin:12px 0 0;padding:0;list-style:none;counter-reset:s}
.adv-steps li{counter-increment:s;position:relative;padding:6px 0 6px 34px;color:var(--body);font-size:15px;line-height:1.45}
.adv-steps li::before{content:counter(s);position:absolute;left:0;top:6px;width:22px;height:22px;border-radius:50%;background:var(--purple-wash);border:1px solid var(--purple-line);color:var(--purple);font-size:12px;font-weight:800;display:flex;align-items:center;justify-content:center}
.adv-trust{display:flex;gap:12px;align-items:flex-start;background:linear-gradient(90deg,var(--gold-soft),#fff 75%);border:1px solid var(--gold-line);border-radius:var(--r-md);padding:var(--space-4);margin-bottom:var(--space-6);font-size:14.5px;line-height:1.5;color:var(--ink)}
.adv-trust svg{flex-shrink:0;margin-top:2px;color:var(--gold-text)}
.adv-form label{display:block;font-size:13.5px;font-weight:700;color:var(--ink);margin:14px 0 0}
.adv-form .adv-opt{font-weight:500;color:var(--faint)}
.adv-form input,.adv-form textarea{display:block;width:100%;margin-top:5px;font:inherit;font-size:15px;padding:10px 12px;border:1px solid var(--field-line);border-radius:var(--r-sm);background:#fff;color:var(--ink)}
.adv-form input:focus,.adv-form textarea:focus{outline:2px solid var(--purple);outline-offset:1px;border-color:transparent}
.adv-err{color:#a12d2d;font-size:14px;font-weight:600;margin-top:12px}
.adv-fine{font-size:13px;color:var(--faint);margin-top:10px}
.adv-back{font-size:14px;font-weight:600;color:var(--purple);text-decoration:none;white-space:nowrap}
.adv-back-short{display:none}
@media(max-width:480px){
  .adv-back .adv-back-long{display:none}
  .adv-back .adv-back-short{display:inline}
  /* 24px of card padding on a 390px phone left text 296px wide. 16 matches
     the reader's own boxes. (The pull-out past the gutter is at the end of
     this sheet with the rest of the phone card family.) */
  .adv-card{padding:var(--space-4)}
}

/* ---------- Phones: headings keep the gutter, cards break out past it ----------
   The hero, the day bars, the section captions and every control (search, view
   toggle, chips, selects) sit at the .wrap gutter. The containers where the
   reading happens -- event lists, the ongoing box, the grid, the map, the
   spotlight, the bands, the /advertise cards -- pull out to 8px from the screen
   edge: -8 at the 16px tier, -4 at the 12px tier. Same rule as the Desk
   (admin.css, end of sheet). Mark, 8/26: "let the headers have the initial
   padding, but the feed and the cards could be wider with less margin."
   LAST in the sheet on purpose: several of these declare their own margin
   shorthand, and an earlier rule loses to them by source order
   (docs/phone-layout-2026-08-26.md). */
@media(max-width:560px){
  .evlist,.ongoing,.grid,#map,.spotlight,.sponsorband,.donateband,.adslot,.adv-card,.adv-trust{margin-left:-8px;margin-right:-8px}
}
@media(max-width:400px){
  .evlist,.ongoing,.grid,#map,.spotlight,.sponsorband,.donateband,.adslot,.adv-card,.adv-trust{margin-left:-4px;margin-right:-4px}
}
