/* ============================================================
   mobile.css — site-wide mobile refinements.
   
   The pages already carry significant phone work in their own
   <style> blocks (most subpages have ~5-10 media queries each).
   This file fills the gaps that turn up at iPhone widths (390px)
   and applies consistent rules to the universal patterns —
   page-header H1s, the footer, section h2s, body type, sticky
   bars — so every page reads cleanly without dragging the
   editorial DNA off the page.
   
   Loaded AFTER each page's inline CSS so it can override.
   Loaded BEFORE topnav.css/scroll-rail.css's own @media blocks
   shouldn't conflict — those handle their own components.
   
   Breakpoint philosophy:
     ≤980  — tablet adjustments (handled per-page inline)
     ≤760  — early-narrow adjustments (handled per-page inline)
     ≤640  — phone proper — this file does its heavy lifting here
     ≤420  — small phone — tighter typography & padding
   ============================================================ */

/* ----- Phone (≤640px) ----- */
@media (max-width: 640px) {

  /* === MULTI-COLUMN PANEL GRIDS that don't collapse ===
     Specific grids found via probe that don't have inline mobile
     fallbacks. The patterns: cfp-banner (4-col), glints (5-col
     city iconography), evenings (3-col), patrons (3-up logos),
     opening keynote billing trio (5-track grid). */
  .cfp-banner-inner,         /* auto 1fr auto auto */
  .glints,                   /* repeat(5, 1fr) */
  .evenings-grid,            /* repeat(3, 1fr) */
  .speaker-grid,             /* repeat(4, 1fr) */
  .tut-grid,                 /* repeat(2, 1fr) */
  .role-grid,                /* repeat(5, 1fr) */
  .case-row,                 /* 1.2fr 1fr */
  .cfp-dates,                /* 1fr 1fr */
  .cfp-grid,                 /* 1fr 1fr */
  .cfp-track,                /* 30px 1fr */
  .effect-grid,              /* 1fr 1fr */
  .effect-stats,             /* repeat(4, 1fr) */
  .venue-hero,               /* 1fr 1fr */
  .venue-facts,              /* 1fr 1fr */
  .city-strip,               /* repeat(3, 1fr) */
  .tables-row,               /* 1fr 1fr */
  .faq-list,                 /* 1fr 1fr */
  .table-ticket .specs,      /* repeat(3, 1fr) */
  .ticket-grid,              /* repeat(3, 1fr) */
  .opening-keynote .ok-billing,
  .opening-keynote .once-triptych,
  .foot-podcast-chips {
    grid-template-columns: 1fr !important;
    gap: 16px !important;
  }
  /* Trip-grid is 3-col tier card row; tickets-grid + offer-grid
     already stacked above. Track-chip etc are tiny visual items. */

  /* === NOWRAP DOTTED-METADATA STREAMS ===
     Many sections use small-caps monospace lines like
     "Tuesday 13 October 2026 · 09:30 — 11:00 · Hall A · Diplomat"
     with `white-space: nowrap` so the dots don't break across
     lines on desktop. At phone width these become 500-600px wide
     and clip on the right. Allow them to wrap on phone. */
  .mark,
  .meta,
  .tier-meta,
  .glint,
  .roman.closer,
  .ok-rule .mark,
  .ok-rule-mark,
  .pl-mark,
  .session-when,
  [class*="-meta"][class*="mono"],
  [class*="meta-line"],
  [class*="dotted-line"] {
    white-space: normal !important;
    word-break: normal;
    overflow-wrap: break-word;
    max-width: 100%;
  }

  /* === RESERVE CTA / STICKY BARS — keep within viewport === */
  .reserve-cta-wrap,
  .reserve-cta,
  .reserve-note,
  .reserve-cta-bar {
    max-width: 100% !important;
    width: 100% !important;
    flex-wrap: wrap;
  }

  /* === GENERIC TIGHT-CAPS HEADER STAMPS ===
     Eyebrows that use letter-spacing 0.3em+ and JetBrains Mono.
     Those text streams have huge intrinsic widths. Allow wrap. */
  .eyebrow,
  [class*="eyebrow"],
  [class*="-stamp"],
  [class*="-tag"]:not(.tag-cloud > *) {
    white-space: normal !important;
  }

  /* === HERO HEADER FIXES ===
     - Globe centering on phone: at desktop the wrap uses
       `margin-left: calc(50% - min(49.5vw, 1176px))` for a
       full-bleed overshoot. That math undershoots on small screens
       and pulls the globe ~26px left of center. Reset to flow
       centering at ≤640px.
     - Globe also has `margin-top: -3cm` on desktop to overlap the
       title with depth — on phone that yanks the globe up into the
       subtitle ("Prague · 13–15 October") and "Conference" caps row.
       Reset margins to a small positive gap. */
  .hero-plasma {
    width: 100% !important;
    max-width: 100% !important;
    margin-left: auto !important;
    margin-right: auto !important;
    margin-top: 24px !important;
    margin-bottom: 12px !important;
    left: auto !important;
    transform: none !important;
  }
  /* Extra top padding on the hero band so the eyebrow
     "PRIVACY AS A FUNDAMENTAL HUMAN RIGHT" sits clear of the
     fixed topnav above (which is ~73px tall on mobile). */
  .hero-title-band {
    padding-top: 120px !important;
    padding-bottom: 16px !important;
  }
  /* Tighten the gap between the H1 and the Conference caps + the
     subtitle so the stack feels intentional, not floating. */
  .hero-title-conference {
    margin-top: 8px !important;
    margin-bottom: 4px !important;
  }
  .hero-subtitle {
    margin-top: 8px !important;
    margin-bottom: 0 !important;
    /* Desktop pulls subtitle up by 19px to overlap the title — on
       phone that drops it INTO the "Conference" caps line. Reset. */
    top: 0 !important;
    position: relative;
  }
  /* === HERO HEADER FIXES (continued) ===
     - Hide .hero-corners (decorative absolute-positioned text in
       the top-L and top-R corners — overlaps the wordmark below
       on phone, producing the chaotic "CORPORATION DIPLOMAT HOTEL
       PRIVACY..." mess).
     - Hide hero-title-conference .ornament (Roman numerals on
       either side of "Conference" — they have min-content widths
       that push the row past viewport).
     - Allow Thema · Munus · Vinculum to wrap (it currently nowraps).
     - Tighten the hero-eyebrow's flanking rules to keep the line
       within viewport. */
  .hero-corners { display: none !important; }
  .hero-title-conference .ornament { display: none !important; }
  .hero-eyebrow .rule { display: none !important; }
  .hero-eyebrow {
    gap: 6px !important;
    flex-wrap: wrap !important;
    justify-content: center !important;
  }
  .tm-head .latin {
    white-space: normal !important;
    line-height: 1.5;
    /* Was 48px on desktop — too big at 375. Scale down hard. */
    font-size: clamp(16px, 4.4vw, 22px) !important;
    letter-spacing: 0.16em !important;
  }
  .tm-head .latin .dot {
    white-space: nowrap;
  }
  /* `Thema · Munus · Vinculum` was clipping past the right edge —
     allow the line to break between phrases. */
  .tm-head .latin {
    display: inline-block;
    max-width: 100%;
    overflow: visible !important;
  }
  /* The arc-lamp figure + caption — two children laid out side by
     side on desktop. On phone the caption becomes a 1-word-per-line
     ribbon. Stack vertically. */
  .tm-arc-figure {
    display: flex !important;
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 20px !important;
  }
  .tm-arc-sketch,
  .tm-arc-fig-caption {
    max-width: 100% !important;
    width: 100% !important;
  }
  .tm-arc-cap {
    display: block;
    line-height: 1.5;
  }

  /* === SPEAKERS BLURB FOOT — text + CTAs were side-by-side
     causing the .left text to wrap one-word-per-line because the
     actions block claimed ~50% width. Stack vertically and let
     the actions sit beneath. */
  .sp-foot {
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 20px !important;
  }
  .sp-foot .left {
    max-width: 100% !important;
  }
  .sp-foot .actions {
    flex-wrap: wrap !important;
    width: 100% !important;
  }
  .sp-foot .actions a {
    flex: 1 1 calc(50% - 7px) !important;
    min-width: 0 !important;
    text-align: center;
  }

  /* === CFP BANNER (index post-hero strip) — the inner is
     `auto 1fr auto auto` four columns: stamp | headline | meta |
     button. At phone width the headline column clips on the right
     and the button gets pushed out. Stack vertically. */
  .cfp-banner-inner {
    grid-template-columns: 1fr !important;
    gap: 12px !important;
    padding: 16px 20px !important;
    text-align: center;
  }
  .cfp-banner-inner .stamp,
  .cfp-banner-inner .headline,
  .cfp-banner-inner .meta,
  .cfp-banner-inner .btn {
    white-space: normal !important;
    text-align: center;
    justify-self: center !important;
  }
  .cfp-banner-inner .btn {
    width: auto;
    margin: 4px auto 0;
  }

  /* === PATRONS / SPONSORS TIER HEADS — `<rule> Partners <meta> <rule>`
     flex row. On phone the rules eat the space and the italic meta
     "in residence at Edition № 02 · Monday 12 October" gets squeezed
     to ~30px wide, wrapping one word per line. Stack the head and
     hide the decorative rules. */
  .patrons-tier-head {
    flex-direction: column !important;
    align-items: center !important;
    gap: 6px !important;
    text-align: center;
  }
  .patrons-tier-head .tier-rule {
    display: none !important;
  }
  .patrons-tier-head .tier-label,
  .patrons-tier-head .tier-meta {
    white-space: normal !important;
    max-width: 100%;
  }
  .patrons-tier-head .tier-meta {
    font-size: 13px !important;
    line-height: 1.4;
  }
  /* Patron cells — already collapse to 1-col at ≤540 per inline
     CSS, but bump max-height on logos so giant SVGs (RIT, Edinburgh
     Napier) don't dominate the column. */
  .patron-cell img {
    max-height: 80px !important;
    width: auto !important;
    max-width: 100% !important;
    object-fit: contain !important;
  }
  /* Square-logo cells (e.g. CHESS) need more room — they're 1:1 marks,
     not wide wordmarks, so the partners-co list-row treatment renders
     them as a 36px thumbnail. Override with higher specificity than
     mobile-patrons.css's foil-ruled list rules. */
  html body .patrons-tier.partners-co .patron-cell.patron-cell--square {
    min-height: 260px !important;
    padding: 24px !important;
    justify-content: center !important;
    flex-direction: column;
  }
  html body .patrons-tier.partners-co .patron-cell.patron-cell--square img {
    max-height: 220px !important;
    max-width: 100% !important;
    object-position: center center !important;
  }

  /* Theme/Mission column headings on phone — were 36px desktop
     which crowds the column at 375. */
  .tm-col h3,
  .tm-col h3 .roman,
  .tm-col h3 em {
    font-size: clamp(24px, 6.5vw, 30px) !important;
    line-height: 1.15 !important;
  }
  /* Theme/Mission column lede + body — keep readable at narrow widths */
  .tm-col p.lede {
    font-size: 17px !important;
    line-height: 1.5 !important;
  }
  .tm-col p:not(.lede) {
    font-size: 16px !important;
    line-height: 1.55 !important;
  }
  /* The `.gloss` italic caption under the binding heading */
  .tm-head .gloss {
    font-size: 14px !important;
    line-height: 1.4 !important;
  }

  /* === DRAWER SUB-MENU COLLAPSE ===
     topnav.css's drawer rule shows all sub-menus expanded by
     default (opacity:1 + position:static). On a long site like
     this that's 6+ extra sub-items per parent — the user has to
     scroll past a wall of text. Collapse them by default and
     reveal on tap (toggled by topnav-mobile.js, which adds
     `.is-open` on the parent `.nav-sub` when its sub-toggle is
     tapped). */
  .topnav .topnav-drawer .nav-sub-menu {
    display: none !important;
    opacity: 0 !important;
    visibility: hidden !important;
    max-height: 0 !important;
    overflow: hidden !important;
    transition: opacity 200ms ease, max-height 280ms ease;
  }
  .topnav .topnav-drawer .nav-sub.is-open .nav-sub-menu {
    display: block !important;
    opacity: 1 !important;
    visibility: visible !important;
    max-height: 800px !important;
  }
  /* Rotate the + indicator to × when open */
  .topnav .topnav-drawer .nav-sub.is-open > .sub-toggle::after {
    content: '×' !important;
  }

  /* === DRAWER SUB-MENU CAPTIONS ===
     The .sm-d helper text under each dropdown menu item ("Mon ·
     full- & half-day workshops" etc) renders at 9.5px. In the
     mobile drawer this is unreadable; bump to 13px. */
  .topnav .topnav-drawer .sm-d,
  .topnav .topnav-drawer .nav-sub-menu .sm-d {
    font-size: 13px !important;
    line-height: 1.4 !important;
  }

  /* === SMALL-TEXT BUMPS ===
     Two spots found below 14px in the mobile audit:
     - `.voice-role` (role line under speaker name in the opening
       keynote triptych — "Co-author · SSLeay · President, OpenSSL
       Corporation") renders at 9px on phone.
     - `.foot-community-sub` (subtitle under the footer "Join the
       community" stamp) renders at 13.5px.
     Both bump to 14px minimum on phone — still reads as "fine print"
     but legible. */
  .voice-role {
    font-size: 14px !important;
    line-height: 1.4 !important;
  }
  .foot-community-sub {
    font-size: 14px !important;
  }

  /* === GENERAL BODY COPY MINIMUM ===
     Belt and braces: ensure no body paragraph or list item renders
     below 14px regardless of the page's own clamp rule. */
  section p,
  section li,
  article p,
  article li {
    font-size: max(14px, var(--body-fz, 16px));
  }

  /* === TOP NAV (mobile) — extra safety nets.
     topnav.css already provides the hamburger toggle + slide-in
     drawer at ≤960px (handled by topnav-mobile.js injection).
     Belt-and-braces: make sure the hamburger is visibly tappable
     and the brand wordmark doesn't push the row wider than vp. */
  .topnav .topnav-toggle {
    min-width: 44px !important;
    min-height: 44px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
  }
  .topnav .right .btn {
    padding: 10px 14px !important;
    font-size: 10px !important;
    letter-spacing: 0.14em !important;
  }
  /* Topnav brand wordmark on phone — show OpenSSL stacked above
     "Conference" so the lockup keeps its identity in the top-right
     without the dates row crowding the small viewport.
        OpenSSL
        Conference
     The dates row stays hidden — too cramped at phone widths. */
  .topnav .brand-dates {
    display: none !important;
  }
  .topnav .brand-em {
    display: block !important;
    font-size: 10px !important;
    letter-spacing: 0.22em !important;
    line-height: 1.1 !important;
    margin-top: 1px !important;
    text-align: right !important;
    text-transform: uppercase !important;
  }
  .topnav .brand-name {
    display: inline-flex !important;
    flex-direction: column !important;
    align-items: flex-end !important;
    gap: 0 !important;
    line-height: 1.05 !important;
  }
  .topnav .brand-event {
    display: block !important;
  }
  .topnav .brand {
    overflow: visible;
    text-overflow: clip;
    white-space: nowrap;
    font-size: 16px !important;
  }
  .topnav .brand-roman {
    font-size: 16px !important;
  }
  /* Center the brand wordmark between hamburger (left) and
     Reserve (right) so the lockup sits balanced. */
  .topnav {
    justify-content: space-between !important;
  }

  /* === SPONSORS — DENSER LOGO GRIDS ===
     Each `.sponsor-tier .logos` was rendering as 1 logo per row on
     phone (a tall vertical strip). Patrons are a *flat list within
     a tier*, not "compare these options" — so 2-up packs them
     denser and the page feels less interminable. */
  .sponsor-tier .logos {
    display: grid !important;
    grid-template-columns: repeat(2, 1fr) !important;
    gap: 16px !important;
    overflow-x: visible !important;
    flex-direction: initial !important;
    width: 100% !important;
  }
  /* Single-entry tiers (Platinum solo) — 1-col so the logo doesn't
     shrink to a 100px thumbnail. */
  .sponsor-tier.platinum .logos {
    grid-template-columns: 1fr !important;
  }
  /* Patrons grids on index — same treatment. */
  .patrons-grid.grid-3,
  .patrons-grid.grid-4 {
    grid-template-columns: repeat(2, 1fr) !important;
    gap: 14px !important;
  }
  .patrons-grid.grid-1 {
    grid-template-columns: 1fr !important;
  }

  /* === SPEAKERS FULL ROSTER ===
     Was 4-col plate tiles on phone — cramped. 3-col gives each
     tile ~98px which fits the plate + name without truncation. */
  .fn-wall {
    grid-template-columns: repeat(3, 1fr) !important;
    gap: 10px !important;
  }
  .fn-tile-name {
    font-size: 12px !important;
  }

  /* === SECTION VERTICAL PADDING SWEEP ===
     Many sections had 80-130px top/bottom padding on desktop, which
     reads as a wall of empty cream paper on a 375px phone. Halve. */
  section,
  header,
  article,
  aside {
    padding-top: 56px !important;
    padding-bottom: 56px !important;
  }
  /* Hero — no extra padding, the title-band has its own. */
  header.hero,
  section.hero {
    padding-top: 0 !important;
    padding-bottom: 0 !important;
  }
  /* Opening keynote keeps a touch more for searchlight + lamps. */
  section.opening-keynote {
    padding-top: 72px !important;
    padding-bottom: 72px !important;
  }

  /* === REGISTER FAQ — already collapses to 1-col. Trim per-item
     vertical padding so the list isn't 4 screens long. */
  .faq-list {
    grid-template-columns: 1fr !important;
    gap: 0 !important;
  }
  .faq-item {
    padding: 18px 0 !important;
  }
  .faq-item h4 {
    font-size: 18px !important;
    line-height: 1.3 !important;
    margin-bottom: 6px !important;
  }
  .faq-item p {
    font-size: 15px !important;
    line-height: 1.5 !important;
  }

  /* ============================================================
     SWIPE GALLERIES — card sets become horizontal scrolling rows
     on phone so users can compare 2-4 related cards by swiping
     instead of vertical-scrolling past each one.
     
     Pattern (Apple App Store / iOS Music):
       - First card fills the screen
       - Next card peeks ~44px from the right edge as a "swipe hint"
       - scroll-snap-type forces clean stops at each card
       - scrollbar hidden but functionality intact (touch + drag)
     
     Applied to:
       index — tickets-grid, offer-grid, once-triptych, e03-strip
       dinners — evenings grid
       speakers — ph-plenary-stack
       tutorials — tut-grid
     ============================================================ */
  .tickets-grid,
  .offer-grid,
  .once-triptych,
  .e03-strip,
  .ph-plenary-grid,
  .evenings-grid,
  .tut-grid {
    /* Override the inline 1fr stacked grid on phone */
    display: flex !important;
    grid-template-columns: none !important;
    flex-direction: row !important;
    overflow-x: auto !important;
    overflow-y: visible !important;
    /* Snap behaviour */
    scroll-snap-type: x mandatory;
    scroll-padding-left: 16px;
    scroll-padding-right: 16px;
    /* Breathing room on each side that matches the section padding,
       so the first card aligns flush with section content. */
    padding: 4px 16px 24px !important;
    /* Cancel my earlier zero-padding override for these specific
       containers — they need their own scrolling padding. */
    margin: 0 -16px !important;  /* break out of section padding */
    /* Children gap */
    gap: 14px !important;
    /* Touch UX */
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  /* Hide the WebKit scrollbar */
  .tickets-grid::-webkit-scrollbar,
  .offer-grid::-webkit-scrollbar,
  .once-triptych::-webkit-scrollbar,
  .e03-strip::-webkit-scrollbar,
  .ph-plenary-grid::-webkit-scrollbar,
  .evenings-grid::-webkit-scrollbar,
  .tut-grid::-webkit-scrollbar {
    display: none;
  }
  /* Each card — flex-basis 85% so the next card peeks ~50px */
  .tickets-grid > *,
  .offer-grid > *,
  .once-triptych > *,
  .e03-strip > *,
  .ph-plenary-grid > *,
  .evenings-grid > *,
  .tut-grid > * {
    flex: 0 0 85% !important;
    min-width: 0 !important;
    max-width: 85% !important;
    scroll-snap-align: start;
    /* Don't let the cards collapse to fit-content; they should
       fill their flex track even if their content is short. */
    height: auto;
  }
  /* The featured ticket card had a desktop translateY(-12px) +
     scale(1.04) to lift visually. In a swipe row that breaks the
     scroll-snap alignment — remove. */
  .tier-card.is-featured,
  .offer-card.is-featured {
    transform: none !important;
  }
  /* Subtle visual cue at the start: a small "› swipe" tail or
     just trust the peek-of-next-card. Skip the explicit hint —
     the peek is the hint. */

  /* For sections where the cards are very tall (full feature
     lists, three keynote voices with portraits etc), prevent
     them from making the whole page lock its height to the
     widest card. */
  .tickets-grid,
  .once-triptych {
    align-items: stretch;
  }
  /* Photo strip — Edition 01 — keep tighter ratio since each
     "card" is just a single photo. */
  .e03-strip > figure {
    flex: 0 0 70% !important;
    max-width: 70% !important;
  }

  /* === CONSISTENT CONTENT WIDTH ===
     The mobile audit showed wildly inconsistent inner widths
     across sections at 375px:
       tier-card / offer-card / e03-inner: 307px (28px L+R)
       tm-col / patrons-inner:             267px (48px L+R)
       cfp-banner-inner / sp-foot:         243px (64px L+R)  ← too tight
       foot-community / variant-a-strip:   331/363px         ← too wide
     Normalise every section to 16px horizontal padding so the
     content spread matches across the page and editorial copy
     uses ~92% of viewport width instead of squeezing to 70%. */
  section,
  header,
  article,
  aside,
  main,
  footer {
    padding-left: 16px !important;
    padding-right: 16px !important;
  }
  /* Tier cards previously used 28px padding inside their own card
     border. Keep that inside the card so the breathing room around
     the type stays elegant. */
  
  /* Inner wrappers that previously had their own horizontal
     padding need to zero out so the section padding alone defines
     the column. */
  .tm-inner,
  .e03-inner,
  .patrons-inner,
  .opening-keynote-inner,
  .cfp-banner-inner,
  .foot-community,
  .foot-flourish,
  .sp-foot,
  .sp-inner,
  .reserve-cta-bar,
  .variant-a-strip,
  .hero-copy,
  .hero-title-band,
  .ok-inner {
    padding-left: 0 !important;
    padding-right: 0 !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    max-width: 100% !important;
  }
  /* Tickets/offers cards keep their inner padding for breathing
     room around the typography inside, but reset any extra outer
     margin so cards align with sibling sections. */
  .tier-card,
  .offer-card {
    margin-left: 0 !important;
    margin-right: 0 !important;
  }
  .variant-a-strip {
    padding-top: 16px !important;
    padding-bottom: 16px !important;
  }
  .foot-community {
    padding-top: 28px !important;
    padding-bottom: 28px !important;
  }

  /* === EDITORIAL HEADINGS — don't wrap to 3+ narrow lines.
     `.ok-title` ("Illuminating the history of SSLeay") had hard
     <br> tags that, at 26px font, wrapped one of the spans into 2
     extra lines. Slightly smaller + drop `text-wrap: balance` so
     each line takes the full column width. */
  .opening-keynote .ok-title {
    font-size: clamp(28px, 7.5vw, 36px) !important;
    line-height: 1.1 !important;
    text-wrap: wrap !important;
  }
  .opening-keynote .once-h {
    font-size: clamp(26px, 7vw, 34px) !important;
    line-height: 1.12 !important;
    text-wrap: wrap !important;
    max-width: 100% !important;
  }

  /* === STOP HORIZONTAL OVERFLOW SITE-WIDE ===
     The root cause across every page: many top-level sections use
     `display: grid` without an explicit `grid-template-columns`,
     defaulting to a single auto-sized column that grows to the
     min-content of the widest child. White-space:nowrap text
     (small-caps wordmarks, JetBrains Mono labels, etc) blows the
     column past the viewport. `overflow:hidden` then clips the
     RIGHT side of the content — exactly the chopped-text on iPhone.

     The canonical fix is `min-width: 0` on grid+flex children
     (which lets them shrink below their min-content) plus a
     `minmax(0, 1fr)` track. */
  html, body {
    overflow-x: hidden;
    overflow-y: auto;
    /* Critical safety net: 100% width on root prevents subpixel
       drift from making the body wider than viewport. */
    width: 100%;
  }

  /* Force grid + flex items to allow shrinking below min-content
     site-wide. Without this, white-space:nowrap children blow
     their grid track past the viewport. */
  body section,
  body header,
  body footer,
  body article,
  body aside,
  body main,
  body nav,
  body figure,
  body div,
  body section > *,
  body header > *,
  body main > *,
  body article > *,
  body footer > * {
    min-width: 0;
    max-width: 100%;
  }
  /* The hero specifically — single-column grid had a min-content
     576px column due to nowrap text. Force fr-shrink. */
  .hero,
  body > main,
  body > header.hero,
  .m-page-header,
  .page-header,
  section[class*="hero"],
  section[class*="manifesto"] {
    grid-template-columns: minmax(0, 1fr) !important;
  }

  /* === HERO HEADER — stop the OpenSSL/CONFERENCE wordmark stack
     from forcing the band wider than the viewport. The desktop
     uses absolute-positioned ornament rules and a tight flex
     layout that assumes generous horizontal real-estate. */
  .hero { padding: 0 16px !important; }
  .hero-title-band {
    padding: 96px 0 24px !important;
    max-width: 100% !important;
  }
  .hero-eyebrow {
    flex-wrap: wrap !important;
    justify-content: center !important;
    gap: 8px 12px !important;
    font-size: 9px !important;
    letter-spacing: 0.22em !important;
  }
  .hero-eyebrow .rule { display: none !important; }
  /* The big title row: "OpenSSL" + small imprint plate side-by-side
     on desktop. Stack vertically and shrink decoration. */
  .hero-title-row {
    flex-direction: column !important;
    gap: 12px !important;
  }
  .hero-title-imprint {
    border-left: 0 !important;
    border-top: 1px solid var(--accent) !important;
    padding-left: 0 !important;
    padding-top: 12px !important;
    height: auto !important;
    align-items: center !important;
    text-align: center !important;
  }
  /* CONFERENCE row — ornamental rules pad out the line. On phone
     the ornament's min-width and ::before rule push the row past
     the viewport. Drop the ornaments. */
  .hero-title-conference .ornament {
    display: none !important;
  }
  .hero-title-conference {
    font-size: clamp(20px, 7.5vw, 32px) !important;
    letter-spacing: 0.18em !important;
    word-break: break-word !important;
  }
  /* Strike + glow are hard-coded 720px absolute positioned; cap
     them to viewport so they don't bleed beyond. */
  .hero-strike,
  .hero-glow {
    width: 100vw !important;
    left: 50% !important;
    transform: translateX(-50%) !important;
  }
  /* Hero subtitle ("Prague · 13–15 Oct") — was nowrap-prone. */
  .hero-subtitle,
  .hero-subtitle-d {
    flex-wrap: wrap !important;
    justify-content: center !important;
    font-size: 18px !important;
    line-height: 1.4 !important;
  }

  /* === EDIT 03 / "WHAT IT LOOKED LIKE" header meta on index.
     Same nowrap dynamic — comma-separated metadata in one line. */
  .e03-head {
    grid-template-columns: 1fr !important;
    gap: 12px !important;
  }
  .e03-head .meta {
    text-align: left !important;
    white-space: normal !important;
  }

  /* === BODY === reduce default body type a touch for legibility
     at narrow widths, so 16-18px body copy doesn't fight the
     editorial italic display type for attention. */
  body {
    -webkit-text-size-adjust: 100%;
  }

  /* === VISA SUPPORT LETTER (register/visa-support-letter.html) ===
     Galaxy S10 fixes:
     1. The §14 stamp-row eyebrow was rendering AT y=64 — behind the
        73px fixed topnav. Push the page-header down so the eyebrow
        clears the nav with breathing room.
     2. The H1 "Crossing the border" runs in a <span class="mtc-h1-line">
        with white-space: nowrap, which overflows the 313px H1 width
        by ~19px on Galaxy S10 and clips the final letter. Allow it
        to wrap. */
  .page-header.mtc-hero,
  header.page-header,
  .mtc-hero.page-header {
    padding-top: 110px !important;
  }
  .mtc-hero h1 .mtc-h1-line,
  .mtc-hero h1 .roman,
  .mtc-hero h1 em {
    white-space: normal !important;
    overflow-wrap: break-word;
  }

  /* === BUTTON TEXT OVERFLOW (phone) ===
     Two screenshots showed "BECOME A SPEAKER" rendering as "BECOM /
     A / SPEAKE" — wrapped to 3 lines AND clipped horizontally. The
     0.18em letter-spacing on caps + 14px padding pushes a half-width
     button below content-width. Tighten letter-spacing & padding on
     buttons inside the .sp-foot pair, and allow them to wrap. */
  .sp-foot .actions {
    flex-wrap: wrap !important;
    gap: 12px !important;
  }
  .sp-foot .actions a,
  .sp-foot .actions .btn {
    flex: 1 1 100% !important;     /* one-button-per-row on phone */
    min-width: 0 !important;
    padding: 14px 16px !important;
    font-size: 12px !important;
    letter-spacing: 0.12em !important;
    white-space: normal !important;
    line-height: 1.3 !important;
    text-align: center;
  }
  /* General button tightening at narrow widths — reduce caps letter-
     spacing so words don't clip. */
  .btn,
  a.btn,
  button.btn {
    letter-spacing: 0.12em !important;
    padding: 12px 16px !important;
  }
  .btn.solid,
  a.btn.solid {
    letter-spacing: 0.14em !important;
    padding: 14px 18px !important;
  }
  /* "SEE THE PROGRAMME" / "BECOME A SPEAKER" / longer button labels
     should never be clipped — let them wrap. */
  .btn,
  a.btn,
  button.btn,
  .btn.solid,
  a.btn.solid {
    white-space: normal !important;
    word-break: keep-all;
    overflow-wrap: normal;
  }

  /* === WORD BREAKING — undo aggressive break-word on italic body
     copy so words like "Submissions" don't split mid-word. */
  .cfp-banner-inner .headline,
  .cfp-banner-inner .meta,
  .cfp-countdown,
  blockquote,
  section p {
    word-break: normal !important;
    overflow-wrap: normal !important;
    hyphens: none !important;
  }

  /* === LATIN BINDING LINE ===
     "Thema · Munus · Vinculum" was still clipping past viewport at
     375 even after font-size shrink — the parent `.tm-head` is
     center-aligned and the latin div is 90%+ width but the chars
     plus letter-spacing exceed it. Reduce letter-spacing AND allow
     the natural word break between phrases. */
  .tm-head .latin {
    font-size: clamp(15px, 4vw, 20px) !important;
    letter-spacing: 0.12em !important;
    padding: 0 10px;
    word-spacing: 0.1em;
    line-height: 1.5;
    white-space: normal !important;
    overflow: visible !important;
  }
  .tm-head .latin .dot {
    margin: 0 2px;
  }

  /* === MAIN TICKET RIBBON ===
     The featured offer card's "Main ticket" decorative ribbon is
     absolute-positioned and overhangs the card to the right by ~24px.
     On phone (single column) that overhang clips off the viewport.
     Tuck it inside the card. */
  .offer-card.is-featured {
    transform: none !important;
    overflow: hidden !important;
  }
  .offer-card.is-featured .main-ticket-tag,
  .offer-card.is-featured [class*="ticket-tag"],
  .offer-card.is-featured [class*="ribbon"] {
    right: 0 !important;
    transform: none !important;
    font-size: 9px !important;
    padding: 4px 8px !important;
  }

  /* === FOLLOW ALONG STRIP ===
     `.variant-a-strip` has flanking ::before/::after rules + a
     "FOLLOW ALONG" label + 3 social icons. At 375 the rules + label
     + icons run over the right edge. Stack the icons under the
     label and hide the decorative rules. */
  .variant-a-strip {
    flex-wrap: wrap !important;
    gap: 12px !important;
    padding: 16px 16px !important;
    justify-content: center;
  }
  .variant-a-strip::before,
  .variant-a-strip::after {
    display: none !important;
  }
  .variant-a-strip .label {
    width: 100%;
    text-align: center;
  }
  .variant-a-strip .icons {
    justify-content: center;
  }

  /* === OFFER FOOT STRIP "4 BENCHES · 80 SEATS · MON 12 OCT" ===
     This caps strip uses webkit-text-stroke + transparent fill on
     desktop for an outline-engraved look. At small viewports the
     stroke renders as 1px white lines on cream paper — illegible.
     Restore solid ink. */
  .offer-foot-strip,
  .offer-foot-strip span,
  [class*="offer-foot"] {
    color: var(--ink, #2A1B0A) !important;
    -webkit-text-fill-color: var(--ink, #2A1B0A) !important;
    -webkit-text-stroke: 0 !important;
    text-shadow: none !important;
    font-size: 10.5px !important;
    letter-spacing: 0.14em !important;
  }

  /* === TUTORIALS NO I CARD — LAMP + DATE LINE FIX ===
     The lamp ornament for the No I offer card was absolute-
     positioned to overlap the top-right. At narrow widths it
     collides with the "Mon 12 Oct" eyebrow above. Push it back
     under the heading line or hide it. */
  .offer-card .offer-lamp,
  .offer-card [class*="lamp"]:not(.lamp-fix) {
    position: relative !important;
    top: auto !important;
    right: auto !important;
    margin: 0 auto 8px !important;
    display: block;
  }

  /* === LAYOUT GRIDS THAT MUST STACK ON PHONE ===
     The big editorial 2-col / 3-col patterns. Many pages assume
     these collapse via inline @media (max-width: 940/980); some
     don't. Cover them all here defensively. */
  .section-head,           /* 240px 1fr — title + meta */
  .sp-head,                /* 240px 1fr auto */
  .session,                /* 90px 1fr 220px — programme rows */
  .scholarship,            /* 200px 1fr auto */
  .table-row-meta,
  .table-ticket,
  .sponsor-tier,           /* 240px 1fr */
  .tm-people-row,          /* 180px 1fr */
  .tm-grid,
  .tm-divider-row,
  .sp-hero,                /* speaker detail: photo | body */
  .speaker-grid,
  .speaker-row,
  .sp-row,
  .voice-card-row,
  .v-row,
  .v-grid,
  .v-split,
  .v-twocol,
  .prague-cards,
  .city-cards,
  .city-card-strip,
  .pager,                  /* PREVIOUS | rule | NEXT footer pager */
  .foot-grid {
    display: grid !important;
    grid-template-columns: 1fr !important;
    gap: 24px !important;
  }
  /* Hide the decorative vertical rule that sat between PREVIOUS / NEXT
     on the pager footer — useless when stacked. */
  .pager-rule, .pager .rule, .tm-divider {
    display: none !important;
  }

  /* === SPEAKER / PROGRAMME 2-COLUMN narrow-right-column.
     Pattern: heading + quote on left, body paragraph on a narrow
     right column. On phone they overlap; force stack. */
  .pl-row,
  .pl-session,
  .pl-talk,
  .pl-row-inner,
  .talk-stripe,
  .talk-row,
  .pl-grid,
  [class*="talk-grid"],
  [class*="session-grid"],
  [class*="programme-grid"] {
    grid-template-columns: 1fr !important;
    display: grid !important;
    gap: 24px !important;
  }

  /* === HORIZONTAL CARD STRIPS that should stack vertically.
     The venue page has a "Linden Leaf | Twin-Tailed Lion |
     Charles Bridge | Astronomical Clock" 4-card row that
     overflows. The dinners page has a 3-card row. */
  .v-strip,
  .v-strip-inner,
  .v-strip-grid,
  .prg-cards,
  .prg-strip,
  .city-strip,
  [class*="city-strip"],
  [class*="strip-grid"] {
    display: grid !important;
    grid-template-columns: 1fr !important;
    overflow-x: visible !important;
    gap: 20px !important;
  }

  /* === SPONSOR / PATRON SECTIONS — RIT, Edinburgh Napier etc.
     The big BACKGROUND lettering ("RIT" in orange) was set as a
     fixed-pixel oversize element behind the patron-card text.
     Clamp it so it doesn't bleed off the screen. */
  .patron-card,
  .patrons-grid > * {
    overflow: hidden !important;
  }
  .patron-card *[class*="bg-letter"],
  .patron-card .bg,
  .patron-card .backdrop,
  .patron-card .backletters,
  .patron-card svg,
  [class*="patron"] *[style*="font-size"] {
    max-width: 100% !important;
    font-size: clamp(48px, 18vw, 96px) !important;
  }
  .patrons-grid {
    grid-template-columns: 1fr !important;
    gap: 16px !important;
  }
  /* Sponsor / patron logos — ensure they max out at viewport width
     and don't overflow their card. */
  .patron-card img,
  .sponsor-tier img,
  .sponsor-card img,
  .tier-logos img {
    max-width: 100% !important;
    width: auto !important;
    height: auto !important;
    max-height: 120px !important;
    object-fit: contain !important;
  }
  /* Some sponsor cards use huge red/orange triangles as decoration.
     They're fine on desktop; clip on phone. */
  .patron-card,
  .sponsor-card {
    overflow: hidden !important;
  }

  /* === PAGER (Previous | Next) FOOTER — currently shows both
     cards SIDE-BY-SIDE at narrow widths, each cut off. Stack. */
  .pager .pager-card,
  .pager-card {
    width: 100% !important;
    max-width: 100% !important;
    text-align: left !important;
  }
  .pager-card.next .sub,
  .pager-card.prev .sub {
    max-width: 100% !important;
  }

  /* === PAGE-HEADER META row — was forced to a single line that
     overflowed. Wrap. */
  .page-header-meta,
  .page-header-inner.page-header-meta {
    flex-wrap: wrap !important;
    gap: 8px 16px !important;
    white-space: normal !important;
  }
  .page-header-meta .item {
    white-space: normal !important;
  }

  /* === SPEAKER PLATE-GRID at speaker.html bottom (Roman-numeral
     thumbnails). 5-column grid that runs off-screen. Reduce. */
  .sp-strip,
  .sp-plate-strip,
  .plate-strip {
    grid-template-columns: repeat(5, minmax(0, 1fr)) !important;
    gap: 6px !important;
    /* Active tile carries a 2px gold ring + glow that the previous
       `overflow:hidden` was clipping at the top edge. Let the ring
       breathe — and give the strip a small inset so the leftmost +
       rightmost tiles have room for their highlight too. */
    overflow: visible !important;
    padding: 6px 4px 4px !important;
    /* The .sp-hero-stage above is locked to min-height: 620px; on a
       narrow phone the active hero card (portrait + name + title +
       CTA button stacked vertically) overflows that container by
       ~50px, which made the bottom of the hero visually land on
       top of this strip's first row. Push the strip down to clear. */
    margin-top: 88px !important;
  }

  /* === LAYOUT GRIDS THAT MUST STACK ON PHONE — closes section === */

  /* === PAGE-HEADER INNER GRID ===
     Most subpages use `.page-header-inner` as a 2-column desktop grid
     (heading | meta side-by-side). At narrow widths the desktop track
     pattern can still fire, squeezing the H1 into a 97px ribbon (venue
     etc). Force single-column on phone. */
  .page-header-inner,
  .page-header-inner.page-header-meta {
    grid-template-columns: 1fr !important;
    gap: 24px !important;
  }

  /* === PAGE-HEADER H1 ===
     Every subpage uses .page-header h1 at clamp(72px, 9vw, 156px)
     with padding-bottom: 1em (after the descender fix). At 390px
     wide the 72px floor still wraps headlines like "Bring your
     work. Take the stage." into 5-6 line crashing blocks.
     Drop to ~52px so it reads as 2-3 lines max. The italic
     descender padding stays. */
  .page-header h1,
  .m-page-header h1 {
    font-size: clamp(40px, 13vw, 56px) !important;
    line-height: 1.05 !important;
    letter-spacing: -0.02em !important;
    /* Newsreader italic "g/y/p" descender at 56px = ~30px below
       line box. 0.6em is enough to absorb without leaving a chasm. */
    padding-bottom: 0.6em !important;
  }
  /* The filament curl decoration sits behind the H1 in an SVG
     positioned bottom:-30px (or -60px on cfp/propose-tutorial).
     At 52px H1 it shrinks proportionally; tuck closer. */
  .page-header h1 > svg[viewBox="0 0 800 200"],
  .m-page-header h1 > svg[viewBox="0 0 800 200"] {
    bottom: -24px !important;
  }

  /* === PAGE-HEADER META row (the small caps "§ Window · Open" 
     blocks under the H1 in propose-tutorial / cfp) — give it
     room to wrap to multiple lines instead of squeezing. */
  .page-header-inner.page-header-meta,
  .page-header-meta {
    flex-wrap: wrap;
    gap: 12px 18px !important;
  }
  .page-header-meta .item {
    flex: 1 1 100%;
  }

  /* === SECTION H2 ===
     Most sections use h2 in the 40-56px range. At 390 wide that
     wraps into a paragraph-sized block. Pull it down to 32-36px
     so it reads as a heading, not a column. */
  section h2 {
    font-size: clamp(26px, 8vw, 36px) !important;
    line-height: 1.1 !important;
    letter-spacing: -0.015em !important;
    /* descender breathing room — same dynamic as page-header */
    padding-bottom: 0.25em;
  }
  /* Specifically the hero h1 / manifesto h1 on index — these
     are the brand statement and CAN run larger. Cap at ~64px so
     "OpenSSL" still reads big without overflowing. */
  .hero-h1,
  .manifesto-h1,
  .hero-title,
  .hero h1 {
    font-size: clamp(44px, 14vw, 64px) !important;
    line-height: 1.04 !important;
    letter-spacing: -0.025em !important;
  }

  /* === FOOTER PADDING ===
     The footer currently has asymmetric padding
     `100px 48px 40px 64px` — 28% of phone width eaten by
     non-content padding. Symmetric, tighter. */
  body > footer,
  footer.site-footer,
  footer:last-of-type {
    padding: 56px 20px 32px !important;
  }

  /* === GENERIC SECTION PADDING ===
     Many sections use 80-110px top/bottom padding. At 390 wide
     that's a wasteful gap. Bring it down. Carefully — only for
     sections that don't override. */
  section[class*="m-"] > .m-body-inner,
  section.m-body { padding: 60px 20px !important; }
  
  /* === BODY COPY — generic <p> in editorial sections === */
  section p:not(.no-shrink) {
    font-size: clamp(16px, 4.4vw, 18px);
    line-height: 1.55;
  }

  /* === HIT TARGETS ===
     Anything tappable below 44×44 fails Apple HIG.
     Buttons inherit but ensure links inside cards get a min target. */
  .btn,
  a.btn,
  button.btn {
    min-height: 44px;
    padding: 12px 20px !important;
  }
  /* Bigger primary action — used heavily on tickets / register */
  .btn.solid,
  a.btn.solid {
    min-height: 48px;
    padding: 14px 24px !important;
    font-size: 13px;
  }

  /* === FORMS ===
     Inputs default to 16px to avoid iOS auto-zoom on focus.
     44px+ tap height. */
  input[type="text"],
  input[type="email"],
  input[type="tel"],
  input[type="url"],
  input[type="number"],
  input[type="search"],
  textarea,
  select {
    font-size: 16px !important;
    min-height: 44px;
  }
  textarea {
    min-height: 88px;
  }

  /* === STICKY BOTTOM BARS (cfp, register, tutorials) ===
     Several pages have a fixed bottom strip with countdown + CTA.
     They overlap content at narrow widths; tighten so the CTA
     stays visible without crushing the page below. */
  .cfp-sticky-bar,
  .tut-sticky-bar,
  .reserve-cta-bar,
  #cfp-sticky-bar {
    padding: 8px 14px !important;
    gap: 12px !important;
  }

  /* === IMAGES — never overflow the viewport === */
  img, video, iframe {
    max-width: 100%;
    height: auto;
  }
  /* The plasma globe iframe is a known exception — it has its
     own aspect-ratio container that handles its own height. */
  .hero-plasma-iframe { max-width: none; height: 100%; }

  /* === BIG GRIDS — ensure 3-up / 2-up grids actually collapse.
     Most pages handle this in inline @media. Defensive fallback. */
  .tickets-grid,
  .ph-plenary-stack,
  .voice-grid,
  .voices,
  .voices-grid,
  .programme-grid,
  .agenda-grid,
  .session-grid,
  .speakers-grid,
  .sponsors-grid {
    grid-template-columns: 1fr !important;
    gap: 20px !important;
  }

  /* === SIDE RAILS / IN-PAGE NAVS that aren't already hidden === */
  .scroll-rail { display: none !important; }
  /* Floor rail — handled by scroll-rail.css already, but ensure
     anything else stays out of the way at narrow widths */
  aside[class*="rail"]:not(.floor-rail) {
    display: none !important;
  }

  /* === Editorial wide blockquotes / pull-quotes — shrink === */
  blockquote {
    font-size: 22px !important;
    line-height: 1.35 !important;
    padding: 12px 0 !important;
    margin: 24px 0 !important;
  }

  /* === Topnav: ensure date stamp doesn't poke through.
     topnav.css already hides .brand-dates, but the brand-em
     occasionally pushes width. Keep the brand lockup tight. */
  .topnav .brand {
    gap: 8px !important;
  }
  .topnav .brand-roman {
    font-size: 14px !important;
  }
  /* brand-em stack rule lives further up — keep this small to
     pair with the OpenSSL line above it without competing. */

  /* === Speaker fn-tile (programme.html plate-style speaker
     thumbnails) — at 3×76 with 12px gap they fit, but 3 columns
     stacked tightly with bold plate labels read cramped. Bump
     to 4 columns at smaller size for a denser scan. */
  .fn-wall {
    grid-template-columns: repeat(4, 1fr) !important;
    gap: 8px !important;
  }
  .fn-tile {
    aspect-ratio: 1/1;
  }
  .fn-tile-name {
    font-size: 11px !important;
  }

}

/* ----- Small phone (≤420px) — squeeze a touch tighter ----- */
@media (max-width: 420px) {
  .page-header h1,
  .m-page-header h1 {
    font-size: clamp(36px, 12vw, 48px) !important;
  }
  section h2 {
    font-size: clamp(24px, 7vw, 32px) !important;
  }
  body > footer,
  footer.site-footer,
  footer:last-of-type {
    padding: 48px 16px 28px !important;
  }
}

/* ----- Landscape phone — prevent runaway H1 height ----- */
@media (max-width: 900px) and (orientation: landscape) and (max-height: 500px) {
  .page-header h1,
  .m-page-header h1 {
    font-size: 44px !important;
    padding-bottom: 0.4em !important;
  }
  .hero-h1, .manifesto-h1 {
    font-size: 48px !important;
  }
}


/* ============================================================
   MOBILE ENHANCEMENT CHROME — surfaces injected by
   mobile-enhancements.js
   ============================================================ */

/* === 01 · Compressed nav on scroll === */
@media (max-width: 640px) {
  body.nav-compressed nav.topnav {
    padding: 8px 14px !important;
    background: rgba(244, 236, 218, 0.96) !important;
    box-shadow: 0 1px 12px rgba(40, 28, 12, 0.08) !important;
    transition: padding 220ms ease, background 220ms ease, box-shadow 220ms ease;
  }
  body.nav-compressed nav.topnav .brand-roman {
    font-size: 14px !important;
    transition: font-size 220ms ease;
  }
  nav.topnav {
    transition: padding 220ms ease, background 220ms ease, box-shadow 220ms ease;
  }
}

/* === 02 · Fade-in images === */
img[loading="lazy"]:not(.img-loaded) {
  opacity: 0;
  filter: blur(8px);
  transition: opacity 420ms ease, filter 420ms ease;
}
img[loading="lazy"].img-loaded {
  opacity: 1;
  filter: blur(0);
}

/* === 03 · Share button (mobile only) === */
.mobile-share-btn { display: none; }
@media (max-width: 640px) {
  .mobile-share-btn {
    position: fixed;
    right: 14px;
    bottom: 18px;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: var(--paper, #FBF5E5);
    border: 1px solid var(--rule-2, rgba(40,28,12,0.22));
    color: var(--ink, #1A1208);
    box-shadow: 0 6px 18px rgba(40,28,12,0.22), 0 1px 0 rgba(255,255,255,0.6) inset;
    cursor: pointer;
    z-index: 80;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: transform 160ms ease, box-shadow 160ms ease;
  }
  .mobile-share-btn:active {
    transform: scale(0.94);
  }
  .mobile-share-toast {
    position: fixed;
    bottom: 88px;
    left: 50%;
    transform: translateX(-50%) translateY(20px);
    background: rgba(26, 18, 8, 0.95);
    color: #F4ECDA;
    padding: 10px 18px;
    border-radius: 6px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 12px;
    letter-spacing: 0.1em;
    opacity: 0;
    transition: opacity 220ms ease, transform 220ms ease;
    pointer-events: none;
    z-index: 90;
  }
  .mobile-share-toast.show {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
  }
}

/* === 04 · Read-progress rail (long pages only, mobile only) === */
.mobile-progress-rail { display: none; }
@media (max-width: 640px) {
  .mobile-progress-rail {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 2px;
    z-index: 95;
    pointer-events: none;
    background: rgba(40, 28, 12, 0.06);
    display: block;
  }
  .mobile-progress-rail-fill {
    display: block;
    height: 100%;
    background: linear-gradient(90deg, #B68A3E 0%, #E8C572 50%, #B68A3E 100%);
    transform-origin: 0 50%;
    transform: scaleX(0);
    transition: transform 80ms linear;
    box-shadow: 0 0 6px rgba(232, 197, 114, 0.5);
  }
}

/* === 05 · Add-to-calendar button (mobile only) === */
.mobile-ics-btn { display: none; }
@media (max-width: 640px) {
  .mobile-ics-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 10px 16px;
    margin-top: 10px;
    background: transparent;
    border: 1px solid var(--rule-2, rgba(40,28,12,0.22));
    color: var(--ink, #1A1208);
    font-family: 'JetBrains Mono', monospace;
    font-size: 10.5px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    text-decoration: none;
    border-radius: 2px;
    transition: border-color 200ms ease, background 200ms ease, color 200ms ease;
  }
  .mobile-ics-btn::before {
    content: '+';
    font-size: 14px;
    line-height: 1;
    margin-right: 4px;
  }
  .mobile-ics-btn:active {
    border-color: var(--filament, #B68A3E);
    background: rgba(229, 199, 122, 0.08);
    color: var(--filament-d, #8a6620);
  }
}


/* ============================================================
   SWIPE-INDICATOR ARROWS + OFFER-CARD FIT-FIXES (phone)
   ============================================================ */
@media (max-width: 640px) {

  /* === Swipe-indicator arrow ===
     Place a small "swipe →" chip floating over the right edge of
     each swipe gallery, anchored to the section so it visually
     belongs to the row of cards. Disappears when the user has
     scrolled the gallery past the first card. */
  .tickets-grid,
  .offer-grid,
  .once-triptych,
  .e03-strip,
  .ph-plenary-grid,
  .evenings-grid,
  .tut-grid {
    position: relative;
  }
  .tickets-grid::after,
  .offer-grid::after,
  .once-triptych::after,
  .e03-strip::after,
  .ph-plenary-grid::after,
  .evenings-grid::after,
  .tut-grid::after {
    content: 'swipe →';
    position: sticky;
    right: 0;
    top: auto;
    bottom: 0;
    align-self: flex-end;
    margin-left: -64px;
    margin-bottom: 8px;
    padding: 6px 12px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 9.5px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    background: rgba(40, 28, 12, 0.85);
    color: #F4ECDA;
    border-radius: 14px;
    flex: 0 0 auto;
    pointer-events: none;
    z-index: 4;
    animation: swipeHintFloat 1.8s ease-in-out infinite;
  }
  @keyframes swipeHintFloat {
    0%, 100% { transform: translateX(0); opacity: 0.85; }
    50%      { transform: translateX(-6px); opacity: 1; }
  }

  /* === Offer-card / tier-card heading sizing ===
     Inside a swipe-gallery card (85% of 375 = ~319 wide, with
     28px internal padding = 263 inner), the desktop heading at
     clamp(32px, 4vw, 52px) renders italic "A hands-on Monday —
     the maintainers, the codebase, and you." wrapping to 11 lines
     of one word each. Cap the heading at 22px so it wraps into
     3-4 lines, not 11. */
  .offer-card .offer-plate h3,
  .offer-card h3 {
    font-size: clamp(20px, 5.5vw, 26px) !important;
    line-height: 1.18 !important;
    word-spacing: normal !important;
  }
  /* Offer-card subhead (italic) — the "A working day with the
     people who build the cryptography you ship" subline. */
  .offer-card .offer-plate .offer-sub,
  .offer-card .offer-plate p.lede {
    font-size: 14px !important;
    line-height: 1.45 !important;
  }
  /* Offer-card "What you take home" bullet list — readable but
     not dominant. */
  .offer-card ul,
  .offer-card .takeaways {
    font-size: 13.5px !important;
    line-height: 1.5 !important;
  }
  /* Offer-card lamp / decorative icon column — if it's a grid
     2-col on desktop (icon | text), force single column on phone
     so text fills the card width instead of getting squeezed. */
  .offer-card .offer-plate,
  .offer-card .offer-head,
  .offer-card .offer-body,
  .offer-card .offer-inner {
    grid-template-columns: 1fr !important;
    display: block !important;
  }
  .offer-card .offer-lamp,
  .offer-card .offer-icon,
  .offer-card [class*="lamp"]:not(.lamp-fix) {
    position: relative !important;
    top: auto !important;
    right: auto !important;
    float: none !important;
    width: 40px !important;
    height: auto !important;
    margin: 0 0 12px !important;
  }

  /* === Tier-card heading inside swipe gallery same dynamic === */
  .tier-card .tier-name-display,
  .tier-card h3,
  .tier-card .tier-head h3 {
    font-size: clamp(22px, 6vw, 28px) !important;
    line-height: 1.15 !important;
  }
  .tier-card .price,
  .tier-card .tier-price {
    font-size: clamp(32px, 9vw, 44px) !important;
    line-height: 1 !important;
  }

}


/* ============================================================
   OFFER-CARD FIT-FIXES (additional) — phone
   ============================================================ */
@media (max-width: 640px) {
  /* The .offer-mark lamp icon takes 56px in the top-right corner
     of the card. The h3 has padding-right: 60px to clear it. At
     254px swipe-card width with 28px internal padding, that
     leaves only 138px for the heading column — squeezes italic
     text into a narrow band. Shrink the mark + drop the h3
     padding-right since the lamp doesn't need that much room. */
  .offer-plate .offer-mark {
    width: 40px !important;
    height: 40px !important;
    top: 10px !important;
    right: 12px !important;
  }
  .offer-plate h3 {
    padding-right: 48px !important;
  }
  .offer-card .offer-plate {
    padding: 18px 18px 8px !important;
  }
  .offer-card .offer-body {
    padding: 16px 18px 20px !important;
  }
  .offer-card .offer-foot,
  .offer-card .offer-foot-strip {
    padding: 14px 18px !important;
  }
}


/* ============================================================
   OFFER-CARD HEADING — final tightening (phone)
   ============================================================ */
@media (max-width: 640px) {
  /* The .offer-mark decorative lamp/inkwell icon was eating ~60px
     of horizontal real-estate from the h3 column at 254px swipe-
     card width, forcing italic headings into 7+ narrow lines.
     Drop the mark on phone — the card title carries the visual
     weight and the mark is reproduced in the offer-foot strip
     below anyway. */
  .offer-plate .offer-mark {
    display: none !important;
  }
  .offer-plate h3 {
    padding-right: 0 !important;
    text-wrap: wrap !important;
    /* Cap heading hard so 3-4 lines max. */
    font-size: clamp(19px, 5.2vw, 24px) !important;
    line-height: 1.15 !important;
  }
  /* Tighten the section h2 above offer cards too — desktop
     "OpenSSL Conference, three days in Prague." was rendering at
     38-64px clamp; phone needs ~28px. */
  .offer-head h2 {
    font-size: clamp(26px, 7.5vw, 36px) !important;
    line-height: 1.1 !important;
  }
}


/* ============================================================
   MOBILE — FOOTER + PADDING + LAST-MILE FIXES (≤640)
   ============================================================ */
@media (max-width: 640px) {

  /* === FOOTER FLOURISH "Praga · Caput · Regni" ===
     The mark line had decorative SVG bands either side that
     constrained the mark to a narrow centre column, breaking the
     three Latin words into one-per-line italic. Hide the bands +
     rules; let the italic line flow naturally. */
  .foot-flourish .rule,
  .foot-flourish svg,
  .foot-end .anv-band,
  .foot-flourish .anv-band {
    display: none !important;
  }
  .foot-flourish {
    flex-direction: column !important;
    gap: 8px !important;
    padding: 24px 16px !important;
    text-align: center;
  }
  .foot-flourish .mark {
    font-size: 22px !important;
    line-height: 1.3 !important;
    white-space: normal !important;
    display: block !important;
    width: auto !important;
    max-width: 100% !important;
    text-align: center;
  }

  /* === FOOTER END (copyright line) ===
     Was rendering as 3 broken columns with mid-word splits.
     Stack as a single centered block on phone. */
  .foot-end {
    display: flex !important;
    flex-direction: column !important;
    align-items: center !important;
    text-align: center !important;
    gap: 6px !important;
    padding: 16px 16px 32px !important;
  }
  .foot-end > * {
    text-align: center !important;
    width: 100% !important;
    max-width: 100% !important;
  }

  /* === OFFER CARD HEADING — final overlord ===
     Multiple earlier rules layered on this — squeeze through
     with a maximally specific selector + nuke text-wrap balance
     which is what's making italic headings wrap into single-word
     ribbons. */
  .offer-grid .offer-card .offer-plate h3,
  .offer-grid .offer-card h3 {
    font-size: clamp(18px, 5.2vw, 22px) !important;
    line-height: 1.2 !important;
    text-wrap: wrap !important;
    text-wrap-style: stable !important;
    word-spacing: normal !important;
    padding-right: 0 !important;
    max-width: 100% !important;
    hyphens: none !important;
  }
  /* The italic em inside the heading carries the same text-wrap */
  .offer-grid .offer-card h3 em {
    text-wrap: wrap !important;
  }

  /* === PATRONS HEAD — tighten gap before CISCO logo ===
     The "A LEDGER OF THE INSTITUTIONS…" gloss line had 56px+
     margin-bottom on desktop; on phone it stacked into ~140px
     of empty cream paper above the first sponsor logo. */
  .patrons-head {
    margin-bottom: 24px !important;
  }
  .patrons-head .gloss {
    margin-bottom: 6px !important;
  }
  .patrons-rule {
    margin: 12px auto 0 !important;
  }
  .patrons-tier {
    margin-bottom: 32px !important;
  }
  .patrons-tier-head {
    margin-bottom: 14px !important;
  }

  /* === PAGER (Previous / Next) — drop the giant gap ===
     The chapter-to-chapter footer pager has 60px+ vertical
     padding around each card and a 96px gap between PREVIOUS
     and NEXT. Tighten to read as one navigation block. */
  .pager,
  [class*="pager"]:not(.pager-rule) {
    padding: 24px 16px !important;
    gap: 16px !important;
  }
  .pager .pager-card,
  .pager-card {
    padding: 16px 0 !important;
  }
  .pager-card h3,
  .pager-card .pager-title,
  .pager-card [class*="title"] {
    font-size: clamp(32px, 8vw, 42px) !important;
    line-height: 1.05 !important;
    margin: 6px 0 !important;
  }

  /* === HERO CTA STACK ===
     "RESERVE A SEAT" + "SEE THE PROGRAMME" + "ADD TO CALENDAR"
     were stacked with 16px+ gaps and a stray scroll-rail "2"
     digit floating off-screen left. Tighten the stack. */
  .hero-cta-row,
  .hero-cta-row--lg {
    flex-direction: column !important;
    gap: 10px !important;
    align-items: stretch !important;
  }
  .hero-cta-row a,
  .hero-cta-row .btn {
    width: 100% !important;
    text-align: center !important;
    justify-content: center !important;
  }
  .hero-cta-row .mobile-ics-btn {
    width: 100% !important;
    justify-content: center !important;
    margin-top: 4px !important;
  }

  /* === GLOBAL — TIGHTER SECTION PADDING ===
     Section vertical 56px was still leaving ~110px of empty
     paper between content. Drop to 36px. */
  section,
  header,
  article,
  aside {
    padding-top: 40px !important;
    padding-bottom: 40px !important;
  }
  /* Hero remains zero — its title-band has its own padding. */
  header.hero,
  section.hero {
    padding-top: 0 !important;
    padding-bottom: 0 !important;
  }
  /* Opening keynote keeps a bit more so the searchlight ornament
     reads as intentional space. */
  section.opening-keynote {
    padding-top: 48px !important;
    padding-bottom: 48px !important;
  }
  /* Patrons plate at the bottom of the homepage — same 40px. */
  section.patrons-plate {
    padding-top: 40px !important;
    padding-bottom: 32px !important;
  }
  /* Theme/mission, edition03 — same dense rhythm. */
  section.theme-mission,
  section.edition03 {
    padding-top: 40px !important;
    padding-bottom: 40px !important;
  }

  /* === REMOVE the stray "2" scroll-rail dot peeking on left ===
     scroll-rail.css positions the dot rail on the right normally;
     ensure it stays hidden at phone widths (we already set it to
     display:none earlier — restate at end of cascade for safety). */
  .scroll-rail,
  nav.scroll-rail,
  aside.scroll-rail {
    display: none !important;
  }

  /* === SWIPE ARROW "swipe →" indicator ===
     The earlier sticky ::after with content:"swipe →" was sometimes
     rendering as a stuck pill on the left of the gallery. Position
     it explicitly at the right-bottom of the scrolled track. */
  .tickets-grid::after,
  .offer-grid::after,
  .once-triptych::after,
  .e03-strip::after,
  .ph-plenary-grid::after,
  .evenings-grid::after,
  .tut-grid::after {
    flex: 0 0 32px !important;
    align-self: center !important;
    margin: 0 !important;
    height: 28px;
    display: inline-flex;
    align-items: center;
  }
}


/* ============================================================
   MISSION PAGE — empty-space cleanup + table fixes (phone)
   ============================================================ */
@media (max-width: 640px) {

  /* === TRIPLET "A mission is a sentence / What it costs is a paid
     staff / Here is ours." ===
     The triplet is 3 m-quote-clause spans in a flex-row container
     that's wrapping each clause into its own narrow column with
     one-word-per-line text. Force flex-column so each clause
     reads as one full line, and gap so they're clearly separated. */
  .m-quote-triplet {
    display: flex !important;
    flex-direction: column !important;
    align-items: stretch !important;
    text-align: center;
    gap: 8px !important;
    padding: 16px 0 !important;
    max-width: 100% !important;
  }
  .m-quote-triplet .m-quote-clause {
    display: block !important;
    width: 100% !important;
    max-width: 100% !important;
    font-size: clamp(17px, 4.6vw, 20px) !important;
    line-height: 1.4 !important;
    white-space: normal !important;
    word-spacing: normal !important;
    text-align: center !important;
  }

  /* === FIVE SURFACES — convert to swipe gallery on phone ===
     Was a 5-col → 2-col → 1-col grid; on phone the 1-col stack
     is a tall vertical strip. Use the same swipe pattern as
     index ticket/offer cards so users can compare surfaces. */
  .m-surfaces {
    display: flex !important;
    grid-template-columns: none !important;
    flex-direction: row !important;
    overflow-x: auto !important;
    overflow-y: visible !important;
    scroll-snap-type: x mandatory;
    scroll-padding-left: 16px;
    padding: 4px 16px 24px !important;
    margin: 0 -16px !important;
    gap: 14px !important;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .m-surfaces::-webkit-scrollbar { display: none; }
  .m-surfaces > * {
    flex: 0 0 80% !important;
    min-width: 0 !important;
    max-width: 80% !important;
    scroll-snap-align: start;
  }
  .m-surfaces::after {
    content: 'swipe →';
    flex: 0 0 32px;
    align-self: center;
    padding: 6px 12px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 9.5px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    background: rgba(40,28,12,0.85);
    color: #F4ECDA;
    border-radius: 14px;
    pointer-events: none;
  }

  /* === MISSION SECTION PADDING — tighter ===
     The mission page sections (m-quote, m-bridge, m-body etc)
     are inheriting the global 40px from my earlier rule, but
     each has its own large inline padding that I haven't fully
     overridden. Drop to 32px and remove the giant inter-section
     gaps. */
  section[class*="m-"],
  section.m-quote,
  section.m-bridge,
  section.m-body,
  section.m-litwindow-stage,
  section.m-body-2,
  aside.m-bridge {
    padding-top: 32px !important;
    padding-bottom: 32px !important;
  }

  /* === TWENTY PEOPLE TABLE ===
     The Five Surfaces and Twenty People tables both have a
     two-column layout: "i. openssl.org | THE LIBRARY". On phone
     the right column is too narrow and breaks text mid-word.
     Force key/value to stack per row. */
  .m-people-row,
  .m-roles-row,
  .m-surface-row,
  [class*="m-people"][class*="grid"],
  [class*="m-roles"][class*="grid"] {
    display: block !important;
    grid-template-columns: 1fr !important;
  }
  .m-people-row > *,
  .m-roles-row > * {
    display: block !important;
    width: 100% !important;
  }

  /* === BIG ITALIC HEADINGS — ensure they don't wrap ridiculously ===
     "It is a small industry. That is the secret, and the constraint."
     "Edition № 02 lands on top of seven concrete things..."
     "Practitioners over pundits. Code over keynotes." */
  .m-body h2,
  .m-body h3,
  .m-quote-text,
  section[class*="m-"] h2,
  section[class*="m-"] h3 {
    font-size: clamp(24px, 6.5vw, 32px) !important;
    line-height: 1.15 !important;
    text-wrap: wrap !important;
  }

  /* === "Black moment" card "And then, last spring, something
     changed" — keep its dark drama but cap padding so it's not
     800px tall on phone. */
  .m-litwindow-stage,
  .litwindow-stage,
  [class*="litwindow"] {
    padding: 56px 20px !important;
  }
  .m-litwindow-stage *,
  [class*="litwindow"] * {
    text-wrap: wrap;
  }

  /* === Stamp lines like § 06 - 4.0 · PQ · X9.146 · 140-3 · BSI ·
     HSM · BRNO · MASARYK — allow wrap === */
  .m-section-stamp,
  [class*="m-section-num"],
  [class*="m-stamp"] {
    white-space: normal !important;
    line-height: 1.45 !important;
  }
}


/* ============================================================
   EDITORIAL POLISH — drop-caps, audience cards, full-bleed
   photos, CTA buttons, section stamps. Mission page-led but
   applied site-wide where the same patterns appear.
   ============================================================ */
@media (max-width: 640px) {

  /* === 01 · KILL DROP CAPS ===
     The big italic "M" / "O" drop caps on long-form paragraphs
     (mission.html "Maintainers and committers", "OpenSSL 4.0 is in
     the field") are sized for a wide column. On phone the rest
     of the paragraph wraps in a narrow gutter alongside a giant
     letter, which reads broken. Normalise. */
  .m-prose > p:first-of-type::first-letter,
  .col-prose > p:first-of-type::first-letter,
  [class*="m-body"] p:first-of-type::first-letter,
  [class*="-prose"] p:first-of-type::first-letter,
  .blog-body p:first-of-type::first-letter,
  article p:first-of-type::first-letter {
    font-size: inherit !important;
    font-weight: inherit !important;
    font-style: inherit !important;
    color: inherit !important;
    float: none !important;
    line-height: inherit !important;
    margin: 0 !important;
    padding: 0 !important;
    background: none !important;
    -webkit-background-clip: initial !important;
    background-clip: initial !important;
    -webkit-text-fill-color: inherit !important;
  }

  /* === 02 · AUDIENCE CARDS — swipe gallery ===
     The 6 "i. Maintainers / ii. Integrators / iii. Distributions /
     iv. Researchers / v. Regulators / vi. Press" cards on mission
     page were stacked vertically. Convert to horizontal swipe so
     the reader compares roles at a glance. */
  .m-audience {
    display: flex !important;
    grid-template-columns: none !important;
    flex-direction: row !important;
    overflow-x: auto !important;
    overflow-y: visible !important;
    scroll-snap-type: x mandatory;
    padding: 4px 16px 24px !important;
    margin: 0 -16px !important;
    gap: 14px !important;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .m-audience::-webkit-scrollbar { display: none; }
  .m-audience > .m-aud-card,
  .m-audience > * {
    flex: 0 0 75% !important;
    max-width: 75% !important;
    min-width: 0 !important;
    scroll-snap-align: start;
  }
  .m-audience::after {
    content: 'swipe →';
    flex: 0 0 auto;
    align-self: center;
    padding: 6px 12px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 9.5px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    background: rgba(40,28,12,0.85);
    color: #F4ECDA;
    border-radius: 14px;
    pointer-events: none;
  }

  /* === 03 · MISSION PAGE CTAs ===
     "SEE WHO'S ON STAGE / SUBMIT A TALK / RESERVE A SEAT" were
     small inline text links. Convert to full-width tappable
     buttons, stacked. */
  [class*="m-body"] .m-cta-row,
  [class*="m-body"] a[href^="cfp"],
  [class*="m-body"] a[href^="speakers"],
  [class*="m-body"] a[href^="register"]:not(.btn),
  .m-prose + .m-cta-list,
  .m-cta-list,
  .m-actions {
    display: flex !important;
    flex-direction: column !important;
    gap: 10px !important;
    align-items: stretch !important;
    margin-top: 18px;
  }
  /* Catch the "SEE WHO'S ON STAGE → / SUBMIT A TALK → / RESERVE
     A SEAT →" trio specifically — they were 3 <a> siblings in a
     div. Render them as bordered pills. */
  .m-body [href$="speakers"],
  .m-body [href$="cfp"],
  .m-body [href$="register/"] {
    display: block !important;
    padding: 14px 18px !important;
    border: 1px solid var(--rule-2, rgba(40,28,12,0.22)) !important;
    background: transparent !important;
    color: var(--ink, #1A1208) !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 11px !important;
    letter-spacing: 0.18em !important;
    text-transform: uppercase !important;
    text-decoration: none !important;
    border-radius: 2px !important;
    text-align: center !important;
    min-height: 44px;
    line-height: 1.2;
  }

  /* === 04 · FULL-BLEED PHOTOS ON MISSION ===
     The team-at-work photo at top of plate, the "floor" photo
     at the bottom, the litwindow photo — let them break out of
     the 16px section padding to feel like printed magazine plates. */
  .m-plate-photo,
  .m-figure,
  .m-team-photo,
  figure.m-plate,
  [class*="m-body"] figure:not(.m-arc-figure),
  [class*="m-quote"] figure {
    margin-left: -16px !important;
    margin-right: -16px !important;
    width: calc(100% + 32px) !important;
    max-width: none !important;
  }
  .m-plate-photo img,
  .m-figure img,
  figure.m-plate img,
  [class*="m-body"] figure img,
  [class*="m-quote"] figure img {
    width: 100% !important;
    display: block;
  }
  /* Caption underneath gets aligned to the inner column again */
  .m-plate-photo figcaption,
  figure.m-plate figcaption,
  [class*="m-body"] figure figcaption {
    padding-left: 16px;
    padding-right: 16px;
    margin-top: 8px;
  }

  /* === 05 · BLACK MOMENT CARD POLISH ===
     "And then, last spring, something changed" — the gilt italic
     "something changed" headline gets a soft pulse so the moment
     feels alive. The "Spring 2026" stamp underneath bumps up
     for readability. */
  .m-litwindow-stage .gilt,
  [class*="litwindow"] .gilt,
  [class*="litwindow"] em {
    animation: missionGiltPulse 4.2s ease-in-out infinite;
  }
  @keyframes missionGiltPulse {
    0%, 100% { text-shadow: 0 0 12px rgba(232,197,114,0.4), 0 0 24px rgba(232,197,114,0.18); }
    50%      { text-shadow: 0 0 18px rgba(232,197,114,0.7), 0 0 36px rgba(232,197,114,0.32); }
  }
  @media (prefers-reduced-motion: reduce) {
    .m-litwindow-stage .gilt,
    [class*="litwindow"] .gilt {
      animation: none !important;
    }
  }
  .m-litwindow-stage [class*="stamp"],
  .m-litwindow-stage [class*="cap"],
  [class*="litwindow"] [class*="stamp"] {
    font-size: 12px !important;
    letter-spacing: 0.26em !important;
  }

  /* === 06 · SECTION NUMBER STAMPS ===
     The § 03 / § 04 / § 06 stamps were 11px and easy to skip
     over. Bump to 13px and give them breathing room above the
     heading they introduce. */
  .m-section-num,
  .m-num,
  [class*="m-body"] [class*="-num"],
  [class*="m-body"] .num,
  section[class*="m-"] > .m-num,
  section[class*="m-"] > [class*="-stamp"] {
    font-size: 13px !important;
    letter-spacing: 0.28em !important;
    margin-bottom: 16px !important;
    line-height: 1.4 !important;
  }

  /* === 07 · NEWSPAPER 2-COL PROSE === */
  .col-prose,
  .m-prose,
  [class*="-prose"][class*="col"] {
    column-count: 1 !important;
    column-rule: none !important;
    max-width: 100% !important;
  }

  /* === 08 · SITE-WIDE APPLICATION ===
     The same patterns appear on other pages — apply where found. */

  /* Blog-post first paragraph drop cap */
  .blog-body p:first-of-type::first-letter,
  article.blog-post p:first-of-type::first-letter {
    font-size: inherit !important;
    float: none !important;
  }

  /* Tutorial bench cards "What you take home" sub-lists already
     stack — no change. */

  /* Speaker detail page — long bio prose first letter */
  .sp-bio p:first-of-type::first-letter,
  .speaker-bio p:first-of-type::first-letter {
    font-size: inherit !important;
    float: none !important;
  }

  /* Cfp tracks intro paragraph drop caps */
  .cfp-tracks p:first-of-type::first-letter,
  .cfp-intro p:first-of-type::first-letter {
    font-size: inherit !important;
    float: none !important;
  }

  /* Generic full-bleed photos on long-form pages */
  .blog-body figure,
  article figure {
    margin-left: -16px !important;
    margin-right: -16px !important;
    width: calc(100% + 32px) !important;
  }
  .blog-body figure img,
  article figure img {
    width: 100% !important;
  }

  /* Generic CTA-row → vertical column on phone */
  .cfp-actions,
  .sp-actions,
  .reg-actions,
  [class*="cta-row"]:not(.hero-cta-row) {
    flex-direction: column !important;
    gap: 10px !important;
    align-items: stretch !important;
  }
  [class*="cta-row"]:not(.hero-cta-row) > a {
    width: 100% !important;
    text-align: center !important;
    justify-content: center !important;
  }
}


/* ============================================================
   MISSION PAGE — DEEP MOBILE FIXES (the patterns that survived)
   ============================================================ */
@media (max-width: 640px) {

  /* === 01 · THE BRIDGE TRIPLET ===
     "A mission is a sentence. What it costs is a paid staff.
     Here is ours." was rendering as THREE NARROW COLUMNS
     side-by-side (each phrase squeezed into 30%-width vertical
     stack). The parent .m-bridge .line uses flex with the
     decorative <span> children floating side-by-side. Force
     it to read as one flowing sentence at full width. */
  .m-bridge .line,
  .m-bridge {
    display: block !important;
    text-align: center !important;
    font-size: clamp(17px, 4.8vw, 22px) !important;
    line-height: 1.55 !important;
    padding: 24px 16px !important;
    max-width: 100% !important;
  }
  .m-bridge .line > span,
  .m-bridge .line > em,
  .m-bridge .line .accent {
    display: inline !important;
    width: auto !important;
    margin: 0 !important;
    white-space: normal !important;
  }
  .m-bridge .line > span::before {
    content: '\A0';
  }

  /* === 02 · LIT WINDOW — fill the mobile width ===
     "PLATE II · The Lit Window" was rendering as a tiny ~80px
     square icon centred in a vast empty cream paper section.
     The figure should fill the mobile width like a printed
     plate. Also reduce the surrounding padding. */
  .m-litwindow-stage,
  [class*="litwindow"]:not(.m-litwindow-stage *) {
    padding: 32px 0 !important;
  }
  .m-litwindow-stage figure,
  .m-litwindow-stage .m-litwindow-photo,
  .m-litwindow-stage img,
  .m-litwindow-stage svg,
  [class*="litwindow"] figure,
  [class*="litwindow"] img {
    width: 100% !important;
    max-width: 100% !important;
    height: auto !important;
    display: block;
    margin-left: 0 !important;
    margin-right: 0 !important;
  }
  /* The window-icon (3 silhouettes inside a frame) is tiny SVG
     by default — scale it up so it reads as the iconic plate it
     was on desktop. */
  .m-litwindow-stage .m-window-sketch,
  .m-litwindow-stage > svg:not(figure svg),
  [class*="litwindow"] > svg:not(figure svg) {
    width: min(280px, 70vw) !important;
    height: auto !important;
    margin: 24px auto !important;
    display: block;
  }
  .m-litwindow-stage figcaption,
  [class*="litwindow"] figcaption {
    padding: 16px 16px 0 !important;
    text-align: center;
  }

  /* === 03 · FIVE SURFACES TABLE ===
     "i. openssl.org | THE LIBRARY", "ii. openssl-corporation |
     SUPPORT · FIPS · REBRAND" etc. The right column was narrow
     and broke the keyword "openssl-communitie..." mid-word.
     Stack key/value per row at phone widths. */
  .m-surfaces-table,
  .m-roles-table,
  [class*="m-surfaces-table"],
  [class*="m-roles-table"],
  table.m-surfaces,
  table.m-roles {
    display: block !important;
    width: 100% !important;
  }
  .m-surfaces-table tbody,
  .m-roles-table tbody,
  [class*="m-surfaces-table"] tbody,
  [class*="m-roles-table"] tbody {
    display: block !important;
  }
  .m-surfaces-table tr,
  .m-roles-table tr,
  [class*="m-surfaces-table"] tr,
  [class*="m-roles-table"] tr {
    display: grid !important;
    grid-template-columns: 32px 1fr !important;
    grid-template-rows: auto auto !important;
    gap: 6px 12px !important;
    border-top: 1px solid var(--rule-2, rgba(40,28,12,0.18)) !important;
    padding: 16px 0 !important;
  }
  .m-surfaces-table tr > *:nth-child(1),
  .m-roles-table tr > *:nth-child(1) {
    grid-row: 1 / 3;
    grid-column: 1;
    font-size: 14px;
    text-align: left;
  }
  .m-surfaces-table tr > *:nth-child(2),
  .m-roles-table tr > *:nth-child(2) {
    grid-row: 1;
    grid-column: 2;
    font-size: 18px !important;
    font-style: italic;
    line-height: 1.25 !important;
    word-break: keep-all;
    overflow-wrap: normal;
    white-space: normal !important;
  }
  .m-surfaces-table tr > *:nth-child(3),
  .m-roles-table tr > *:nth-child(3) {
    grid-row: 2;
    grid-column: 2;
    font-family: 'JetBrains Mono', monospace;
    font-size: 10.5px !important;
    letter-spacing: 0.22em !important;
    text-transform: uppercase;
    color: var(--muted, #6B5A36) !important;
    font-style: normal !important;
    white-space: normal !important;
    line-height: 1.45 !important;
  }
  /* If the data isn't in <table> but in divs (m-aud-card style) */
  .m-surface-row,
  .m-role-row {
    display: grid !important;
    grid-template-columns: 32px 1fr !important;
    gap: 6px 12px !important;
    padding: 14px 0 !important;
    border-top: 1px solid var(--rule-2, rgba(40,28,12,0.18));
  }

  /* === 04 · TIGHTER SECTION GAPS on mission ===
     "§ 07 Practitioners over pundits · Code over keynotes" was
     followed by ~200px of empty cream before the photo. Cut
     the after-stamp / before-image gaps. */
  .m-section-num + h2,
  .m-section-num + h3,
  [class*="-num"] + h2,
  [class*="-num"] + h3 {
    margin-top: 10px !important;
  }
  section[class*="m-"] figure {
    margin-top: 18px !important;
    margin-bottom: 18px !important;
  }
  section[class*="m-"] > * + figure {
    margin-top: 0 !important;
  }
  /* The thin gilt-dot rule between paragraphs and section stamps */
  [class*="m-rule"],
  [class*="m-divider"] {
    margin-top: 16px !important;
    margin-bottom: 16px !important;
  }
  /* The dot inscription "•" floating in empty paper — its parent
     is probably a flex/grid that's too tall. */
  [class*="m-dot-pip"]:empty,
  [class*="m-pip"]:empty {
    margin: 8px auto !important;
  }

  /* === 05 · KILL EXCESS EMPTY VERTICAL SPACE ===
     Mission's sections (m-quote, m-body, m-litwindow-stage,
     m-bridge etc.) cumulatively add 80-120px of padding-top each.
     Phone needs a much denser rhythm. */
  section.m-quote,
  section.m-bridge,
  section.m-body,
  section.m-body-2,
  section.m-litwindow-stage,
  aside.m-bridge,
  .m-quote,
  .m-bridge,
  .m-body,
  .m-litwindow-stage {
    padding-top: 24px !important;
    padding-bottom: 24px !important;
  }
  /* Section heads — tighten the bottom margin so the heading
     doesn't sit in mid-section with empty paper underneath. */
  .m-section-head,
  [class*="m-section-head"] {
    margin-bottom: 16px !important;
    padding-bottom: 0 !important;
  }
}


/* ============================================================
   MISSION — LEDGER + LIT WINDOW (THE ACTUAL CLASS NAMES)
   ============================================================ */
@media (max-width: 640px) {

  /* === LIT WINDOW SVG ===
     The .m-litwindow-svg renders inside the figure at ~280px wide
     by inherited max-width:380px. Push to fill the mobile width
     properly — minus a touch of breathing room. */
  .m-litwindow-svg,
  figure.m-litwindow svg,
  .m-litwindow-stage svg.m-litwindow-svg {
    width: 100% !important;
    max-width: 90vw !important;
    height: auto !important;
    aspect-ratio: 1 / 1 !important;
    display: block;
    margin: 0 auto !important;
  }
  .m-litwindow-stage-inner {
    max-width: 100% !important;
    padding: 0 !important;
  }
  .m-litwindow-stage figure.m-litwindow {
    max-width: 100% !important;
    width: 100% !important;
    margin: 0 !important;
  }
  /* Cut the surrounding padding so the lit window sits tight in
     its section, not floating in 100px of cream paper. */
  .m-litwindow-stage,
  aside.m-litwindow-stage {
    padding: 24px 16px !important;
  }

  /* === LEDGER FRAME (this is "Five Surfaces" AND "Twenty People")
     The ledger rows are .m-ledger-head + .m-ledger-row inside
     .m-ledger-frame. Desktop is a 4-col grid (Nº | Role | What
     they carry | Posted). The existing inline @media at narrower
     widths drops to 3-col which still wraps one-word-per-line
     because the parent .m-grid is squeezing the frame to ~210px
     wide. Break it free + stack vertically. */
  .m-ledger-frame {
    width: 100% !important;
    max-width: 100% !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    grid-column: 1 / -1 !important;
  }
  /* Promote the frame out of any narrow .m-grid containing it */
  .m-grid .m-ledger-frame,
  .m-grid > .m-ledger-frame {
    grid-column: 1 / -1 !important;
  }

  /* Hide the column header row — it doesn't read well in a
     stacked layout. */
  .m-ledger-head {
    display: none !important;
  }

  /* Each row becomes its own card: numeral + role-on-one-line +
     a small caps "posted" caption underneath. */
  .m-ledger-row {
    display: grid !important;
    grid-template-columns: 32px 1fr !important;
    grid-template-rows: auto auto !important;
    column-gap: 12px !important;
    row-gap: 4px !important;
    padding: 14px 0 !important;
    border-top: 1px solid var(--rule-2, rgba(40,28,12,0.18)) !important;
    align-items: baseline !important;
  }
  .m-ledger-row > .nm {
    grid-row: 1 / 3 !important;
    grid-column: 1 !important;
    font-size: 13px !important;
    color: var(--gilt, #B68A3E) !important;
    align-self: start !important;
    padding-top: 3px;
  }
  .m-ledger-row > .role {
    grid-row: 1 !important;
    grid-column: 2 !important;
    font-size: 17px !important;
    line-height: 1.35 !important;
    word-break: keep-all !important;
    overflow-wrap: normal !important;
    white-space: normal !important;
    color: var(--ink, #1A1208) !important;
  }
  .m-ledger-row > .role .lede {
    font-weight: 500 !important;
    margin-right: 4px !important;
  }
  .m-ledger-row > .surf,
  .m-ledger-row > .place {
    grid-row: 2 !important;
    grid-column: 2 !important;
    display: block !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10px !important;
    letter-spacing: 0.2em !important;
    text-transform: uppercase !important;
    color: var(--muted, #6B5A36) !important;
    font-style: normal !important;
    line-height: 1.4 !important;
    white-space: normal !important;
  }
  /* The ledger foot row (Counted at start / ≈ 20 souls total) */
  .m-ledger-foot {
    display: flex !important;
    flex-direction: column !important;
    gap: 8px !important;
    align-items: center !important;
    padding: 18px 0 !important;
    border-top: 1px solid var(--rule-2, rgba(40,28,12,0.18)) !important;
    text-align: center;
  }

  /* === If the SAME ledger pattern is used elsewhere (the
     "Five Surfaces" plate uses similar markup), force the
     same per-row stacking. */
  [class*="surfaces-row"],
  [class*="surface-row"],
  .m-surfaces > * {
    display: grid !important;
    grid-template-columns: 32px 1fr !important;
    grid-template-rows: auto auto !important;
    gap: 4px 12px !important;
    padding: 14px 0 !important;
    border-top: 1px solid var(--rule-2, rgba(40,28,12,0.18)) !important;
  }
  .m-surfaces {
    display: block !important;
    grid-template-columns: none !important;
    overflow-x: visible !important;
    padding: 0 !important;
    margin: 0 !important;
  }
  .m-surfaces::after {
    display: none !important;
  }

  /* === FORCE .m-grid TO STACK ON PHONE ===
     The mission page wraps the ledger inside .m-grid with desktop
     3-col layout. Existing inline @media collapses to 1-col only
     at 980px. Below 640px the grid is still narrow because of
     parent flex math. Force it. */
  .m-grid,
  .m-grid.single {
    display: block !important;
    grid-template-columns: 1fr !important;
  }
  .m-grid > .col-side,
  .m-grid > .m-side {
    display: block !important;
    width: 100% !important;
    margin-bottom: 16px !important;
  }
  .m-grid > .col-prose,
  .m-grid > .m-prose,
  .m-grid > .m-ledger-frame {
    column-count: 1 !important;
    column-rule: none !important;
    width: 100% !important;
    max-width: 100% !important;
    grid-column: 1 !important;
  }
}


/* ============================================================
   LIT WINDOW — FILL THE MOBILE SCREEN
   ============================================================ */
@media (max-width: 640px) {
  /* Break the figure out of the section's 16px horizontal padding
     so it actually fills edge-to-edge on phone, then size the SVG
     to fill that. */
  section.m-litwindow-stage,
  .m-litwindow-stage {
    padding-left: 0 !important;
    padding-right: 0 !important;
    overflow: hidden !important;
  }
  .m-litwindow-stage-inner {
    max-width: 100% !important;
    padding: 0 !important;
    margin: 0 !important;
    width: 100% !important;
  }
  .m-litwindow-stage figure.m-litwindow,
  figure.m-litwindow {
    width: 100% !important;
    max-width: 100% !important;
    margin: 0 !important;
    padding: 0 !important;
  }
  /* The SVG itself — override the inline 380px max-width with
     full viewport width. */
  .m-litwindow-svg,
  figure.m-litwindow svg.m-litwindow-svg,
  .m-litwindow-stage svg.m-litwindow-svg {
    width: 100% !important;
    max-width: 100% !important;
    height: auto !important;
    aspect-ratio: 1 / 1 !important;
    display: block !important;
    margin: 0 !important;
  }
  /* The caption + any inscription below the window — re-pad them
     to the column gutter since we broke the figure full-bleed. */
  .m-litwindow-stage figcaption,
  .m-litwindow-stage [class*="inscription"],
  .m-litwindow-stage [class*="caption"] {
    padding-left: 16px !important;
    padding-right: 16px !important;
    margin-top: 14px !important;
  }
}


/* ============================================================
   FIVE SURFACES + ROLES — TAPPABLE CARDS (phone)
   ============================================================ */
@media (max-width: 640px) {
  /* The five .m-surface anchors and the .m-ledger-row entries
     share the same data shape: index + label + tag + arrow. On
     phone, render each as a tappable card with the arrow floated
     top-right. */
  .m-surfaces {
    display: flex !important;
    flex-direction: column !important;
    gap: 8px !important;
    overflow: visible !important;
    padding: 0 !important;
    margin: 0 !important;
    grid-template-columns: none !important;
  }
  .m-surfaces::after { display: none !important; }
  .m-surface,
  a.m-surface {
    display: grid !important;
    grid-template-columns: 28px 1fr 22px !important;
    grid-template-rows: auto auto !important;
    column-gap: 12px !important;
    row-gap: 2px !important;
    align-items: baseline !important;
    padding: 16px 14px !important;
    background: rgba(244, 236, 218, 0.55) !important;
    border: 1px solid rgba(40, 28, 12, 0.14) !important;
    border-radius: 4px !important;
    text-decoration: none !important;
    color: var(--ink, #1A1208) !important;
    min-height: 64px !important;
    transition: background 180ms ease, border-color 180ms ease, transform 120ms ease;
  }
  .m-surface:active {
    transform: scale(0.98);
    background: rgba(229, 199, 122, 0.16) !important;
    border-color: var(--filament, #B68A3E) !important;
  }
  .m-surface .num,
  .m-surface > *:first-child {
    grid-row: 1 / 3;
    grid-column: 1;
    font-family: 'Newsreader', Georgia, serif;
    font-style: italic;
    font-size: 15px;
    color: var(--gilt, #B68A3E);
    align-self: start;
    padding-top: 4px;
  }
  .m-surface .ttl,
  .m-surface .domain,
  .m-surface > *:nth-child(2) {
    grid-row: 1;
    grid-column: 2;
    font-family: 'Newsreader', Georgia, serif;
    font-style: italic;
    font-size: 18px !important;
    line-height: 1.2 !important;
    color: var(--ink) !important;
    word-break: keep-all;
    overflow-wrap: normal;
    white-space: normal !important;
  }
  .m-surface .tag,
  .m-surface .sub,
  .m-surface > *:nth-child(3):not(.arr):not(.arrow) {
    grid-row: 2;
    grid-column: 2;
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px !important;
    letter-spacing: 0.22em !important;
    text-transform: uppercase !important;
    color: var(--muted, #6B5A36) !important;
    font-style: normal !important;
    line-height: 1.4 !important;
    margin-top: 2px;
  }
  .m-surface .arr,
  .m-surface .arrow,
  .m-surface .ext {
    grid-row: 1 / 3;
    grid-column: 3;
    align-self: center;
    justify-self: end;
    color: var(--gilt, #B68A3E);
    font-size: 16px;
    line-height: 1;
  }
  /* If the surface uses a plain text "↗" without a span wrapper,
     it gets handled by the auto-arrow content below. */
  .m-surface:not(:has(.arr)):not(:has(.arrow))::after {
    content: '↗';
    grid-row: 1 / 3;
    grid-column: 3;
    align-self: center;
    justify-self: end;
    color: var(--gilt);
    font-size: 16px;
  }

  /* ============================================================
     SAME TREATMENT for the Ledger rows (Roles / Twenty People)
     ============================================================ */
  .m-ledger-row {
    background: rgba(244, 236, 218, 0.4);
    border: 1px solid rgba(40, 28, 12, 0.10) !important;
    border-radius: 4px !important;
    padding: 14px 14px !important;
    margin-bottom: 6px !important;
    border-top: 1px solid rgba(40, 28, 12, 0.10) !important;
  }
}


/* ============================================================
   FIVE DOORS (Surfaces) — actual class names: .m-doors / .m-door
   ============================================================ */
@media (max-width: 640px) {
  .m-doors {
    display: flex !important;
    flex-direction: column !important;
    gap: 8px !important;
    overflow: visible !important;
    padding: 0 !important;
    margin: 0 !important;
    grid-template-columns: none !important;
  }
  .m-door {
    display: grid !important;
    grid-template-columns: 32px 1fr 22px !important;
    grid-template-rows: auto auto !important;
    column-gap: 12px !important;
    row-gap: 2px !important;
    align-items: baseline !important;
    padding: 16px 14px !important;
    background: rgba(244, 236, 218, 0.55) !important;
    border: 1px solid rgba(40, 28, 12, 0.14) !important;
    border-radius: 4px !important;
    text-decoration: none !important;
    color: var(--ink, #1A1208) !important;
    min-height: 64px !important;
    transition: background 180ms ease, border-color 180ms ease, transform 120ms ease;
  }
  .m-door:active {
    transform: scale(0.985);
    background: rgba(229, 199, 122, 0.16) !important;
    border-color: var(--filament, #B68A3E) !important;
  }
  .m-door-num {
    grid-row: 1 / 3 !important;
    grid-column: 1 !important;
    font-family: 'Newsreader', Georgia, serif !important;
    font-style: italic !important;
    font-size: 15px !important;
    color: var(--gilt, #B68A3E) !important;
    align-self: start !important;
    padding-top: 4px !important;
    margin: 0 !important;
  }
  .m-door-body {
    grid-row: 1 / 3 !important;
    grid-column: 2 !important;
    display: flex !important;
    flex-direction: column !important;
    gap: 2px !important;
    min-width: 0 !important;
  }
  .m-door-nm {
    font-family: 'Newsreader', Georgia, serif !important;
    font-style: italic !important;
    font-size: 18px !important;
    line-height: 1.2 !important;
    color: var(--ink) !important;
    word-break: keep-all !important;
    overflow-wrap: normal !important;
    white-space: normal !important;
  }
  .m-door-tag,
  .m-door-sub {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10px !important;
    letter-spacing: 0.22em !important;
    text-transform: uppercase !important;
    color: var(--muted, #6B5A36) !important;
    font-style: normal !important;
    line-height: 1.4 !important;
    margin-top: 2px !important;
  }
  .m-door-leader {
    display: none !important;
  }
  .m-door-arrow {
    grid-row: 1 / 3 !important;
    grid-column: 3 !important;
    align-self: center !important;
    justify-self: end !important;
    color: var(--gilt, #B68A3E) !important;
    font-size: 16px !important;
    line-height: 1 !important;
  }
}


/* ============================================================
   AUDIENCE CARDS — text overlap fix (phone)
   ============================================================ */
@media (max-width: 640px) {
  /* The .m-aud-card uses an absolute-positioned numeral i. / ii. /
     iii. on top of the card with the title overlapping it on
     desktop (intentional editorial effect). On phone the numeral
     ends up crashing into the role title ("Maintainers.") because
     the swipe-gallery card width is too narrow for the desktop
     offset. Drop the numeral into normal flow above the title. */
  .m-aud-card,
  [class*="m-aud"][class*="card"] {
    display: flex !important;
    flex-direction: column !important;
    padding: 18px 16px !important;
    gap: 6px !important;
    overflow: hidden !important;
  }
  .m-aud-card > .num,
  .m-aud-card .m-aud-num,
  .m-aud-card [class*="-num"]:not([class*="surface"]) {
    position: static !important;
    top: auto !important;
    left: auto !important;
    right: auto !important;
    transform: none !important;
    font-family: 'Newsreader', Georgia, serif !important;
    font-style: italic !important;
    font-size: 14px !important;
    color: var(--gilt, #B68A3E) !important;
    margin: 0 0 4px !important;
    line-height: 1 !important;
    opacity: 1 !important;
    z-index: auto !important;
  }
  .m-aud-card .ttl,
  .m-aud-card h3,
  .m-aud-card [class*="-ttl"] {
    position: static !important;
    font-size: 22px !important;
    line-height: 1.2 !important;
    margin: 0 0 8px !important;
    padding: 0 !important;
    white-space: normal !important;
    word-break: keep-all !important;
    overflow-wrap: normal !important;
  }
  .m-aud-card .sub,
  .m-aud-card .tag,
  .m-aud-card [class*="-sub"],
  .m-aud-card [class*="-tag"]:not([class*="surface"]) {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10px !important;
    letter-spacing: 0.22em !important;
    text-transform: uppercase !important;
    color: var(--muted, #6B5A36) !important;
    margin: 0 !important;
    line-height: 1.5 !important;
  }
  .m-aud-card p,
  .m-aud-card .lede {
    font-size: 14px !important;
    line-height: 1.5 !important;
    margin: 6px 0 0 !important;
    color: var(--ink) !important;
  }
  /* The decorative bottom "Patches. Releases. The 4.0 line." line —
     give it room and ensure it doesn't sit ON TOP of body copy. */
  .m-aud-card .m-aud-foot,
  .m-aud-card [class*="-foot"] {
    position: static !important;
    margin-top: 12px !important;
    padding-top: 12px !important;
    border-top: 1px solid rgba(40,28,12,0.12) !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10px !important;
    letter-spacing: 0.18em !important;
    text-transform: uppercase !important;
    color: var(--muted, #6B5A36) !important;
    line-height: 1.5 !important;
  }
}


/* ============================================================
   LEDGER ROW — fix overlapping .place and .surf (phone)
   ============================================================ */
@media (max-width: 640px) {
  /* The ledger has 4 children — .nm, .role, .place, .surf.
     My earlier 2-row grid assigned BOTH .place AND .surf to row 2
     column 2 — they were stacking on top of each other. Switch to
     a 3-row stack: role / place / surf, each on its own row. */
  .m-ledger-row {
    display: grid !important;
    grid-template-columns: 32px 1fr !important;
    grid-template-rows: auto auto auto !important;
    column-gap: 12px !important;
    row-gap: 4px !important;
    padding: 14px 14px !important;
    align-items: baseline !important;
  }
  .m-ledger-row > .nm {
    grid-row: 1 / 4 !important;
    grid-column: 1 !important;
    font-family: 'Newsreader', Georgia, serif !important;
    font-style: italic !important;
    font-size: 14px !important;
    color: var(--gilt, #B68A3E) !important;
    align-self: start !important;
    padding-top: 3px !important;
  }
  .m-ledger-row > .role {
    grid-row: 1 !important;
    grid-column: 2 !important;
    font-family: 'Newsreader', Georgia, serif !important;
    font-style: normal !important;
    font-size: 17px !important;
    line-height: 1.3 !important;
    color: var(--ink, #1A1208) !important;
    word-break: keep-all !important;
    overflow-wrap: normal !important;
    white-space: normal !important;
  }
  .m-ledger-row > .role .lede {
    font-weight: 500 !important;
    font-style: italic !important;
    margin-right: 4px !important;
    color: var(--ink, #1A1208) !important;
  }
  .m-ledger-row > .place {
    grid-row: 2 !important;
    grid-column: 2 !important;
    font-family: 'Newsreader', Georgia, serif !important;
    font-style: italic !important;
    font-size: 14px !important;
    color: var(--muted-2, #8a7c54) !important;
    line-height: 1.4 !important;
    white-space: normal !important;
    margin: 4px 0 0 !important;
  }
  .m-ledger-row > .surf {
    grid-row: 3 !important;
    grid-column: 2 !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10px !important;
    letter-spacing: 0.22em !important;
    text-transform: uppercase !important;
    color: var(--muted, #6B5A36) !important;
    line-height: 1.5 !important;
    margin: 2px 0 0 !important;
  }
}


/* ============================================================
   "AND THEN, LAST SPRING, SOMETHING CHANGED" — bigger on phone
   ============================================================ */
@media (max-width: 640px) {
  /* The pivot bridge has the gilt italic "something changed" headline.
     Desktop uses clamp(48px, 7vw, 88px) which on phone resolves to
     the floor (48px). Bump the floor so it reads as the *moment* it
     is — bigger than the surrounding bridge sentences. */
  .m-bridge--pivot .line,
  .m-bridge--pivot {
    padding: 48px 16px !important;
    text-align: center;
  }
  .m-bridge--pivot .line {
    font-size: clamp(38px, 11.5vw, 56px) !important;
    line-height: 1.05 !important;
    letter-spacing: -0.02em !important;
  }
  /* The italic gilt span "something changed" inside — same size, the
     animated sheen carries the brand moment. */
  .m-bridge--pivot .line span,
  .m-bridge--pivot .line em {
    font-size: inherit !important;
    display: inline !important;
    line-height: inherit !important;
  }
  /* The stamp "the moment the wave broke · spring 2026" underneath —
     small monospace, breathing room above. */
  .m-bridge--pivot .stamp {
    margin-top: 18px !important;
    font-size: 10px !important;
    letter-spacing: 0.24em !important;
    line-height: 1.5 !important;
  }
}


/* ============================================================
   MISSION — swipe indicators wherever cards swipe (phone)
   ============================================================ */
@media (max-width: 640px) {
  /* .m-audience is already a swipe gallery via earlier rule but
     lacks a visible swipe-hint chip. Add one. */
  .m-audience {
    position: relative;
  }
  .m-audience::after {
    content: 'swipe →';
    flex: 0 0 auto !important;
    align-self: center !important;
    margin: 0 !important;
    padding: 6px 12px !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 9.5px !important;
    letter-spacing: 0.22em !important;
    text-transform: uppercase !important;
    background: rgba(40,28,12,0.85) !important;
    color: #F4ECDA !important;
    border-radius: 14px !important;
    pointer-events: none !important;
    display: inline-flex !important;
    align-items: center !important;
    height: 28px;
    animation: swipeHintFloat 1.8s ease-in-out infinite;
  }
}


/* ============================================================
   CFP PAGE — mobile layout fixes
   ============================================================ */
@media (max-width: 640px) {

  /* === The 4 cfp-track-card cards were rendering as 149×1373px
     tall skinny columns side-by-side. Convert to swipe gallery
     so each track gets a full-readable card width. === */
  .cfp-tracks-grid,
  .cfp-tracks,
  .cfp-tracks-row,
  .cfp-track-card:first-child {
    /* If parent has no class, target the parent via :has() */
  }
  /* Target the parent of cfp-track-card directly — it has no class */
  .cfp-track-card {
    /* Reset card sizing */
  }
  *:has(> .cfp-track-card) {
    display: flex !important;
    flex-direction: row !important;
    overflow-x: auto !important;
    overflow-y: visible !important;
    grid-template-columns: none !important;
    scroll-snap-type: x mandatory;
    padding: 4px 16px 24px !important;
    margin: 0 -16px !important;
    gap: 14px !important;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    position: relative;
  }
  *:has(> .cfp-track-card)::-webkit-scrollbar { display: none; }
  .cfp-track-card {
    flex: 0 0 85% !important;
    min-width: 0 !important;
    max-width: 85% !important;
    height: auto !important;
    scroll-snap-align: start;
  }
  /* Swipe hint chip */
  *:has(> .cfp-track-card)::after {
    content: 'swipe →';
    flex: 0 0 auto !important;
    align-self: center !important;
    padding: 6px 12px !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 9.5px !important;
    letter-spacing: 0.22em !important;
    text-transform: uppercase !important;
    background: rgba(40,28,12,0.85) !important;
    color: #F4ECDA !important;
    border-radius: 14px !important;
    pointer-events: none !important;
    display: inline-flex !important;
    align-items: center !important;
    height: 28px;
  }

  /* === "Where your work belongs." H2 ===
     The inline-styled h2 has clamp(56px, 7vw, 108px) which on
     phone hits the 56px floor. With the hard <br> between "Where
     your" and "work belongs", and 26px of text + descender, it
     creates an awkward 2-line crash. Tighten + soften. */
  .cfp-where h2,
  section h2[style*="clamp(56px"],
  section [style*="clamp(56px,7vw,108px)"] {
    font-size: clamp(36px, 10vw, 48px) !important;
    line-height: 1.05 !important;
    letter-spacing: -0.025em !important;
  }

  /* === The "§ I — The Tracks · Four halls, four conversations"
     stamp row — its inline flex pip pushes the second phrase off
     the line on phone. Stack vertically. === */
  .stamp-row {
    display: flex !important;
    flex-direction: column !important;
    align-items: center !important;
    gap: 4px !important;
    text-align: center !important;
    margin-bottom: 16px !important;
  }
  .stamp-row .pip {
    width: 20px !important;
    height: 1px !important;
    background: var(--rule-2, rgba(40,28,12,0.22)) !important;
    margin: 4px 0 !important;
  }
  .stamp-row > span {
    font-size: 11px !important;
    letter-spacing: 0.2em !important;
    line-height: 1.4 !important;
  }
}


/* ============================================================
   CFP — Six Fields, Review Process (phone)
   ============================================================ */
@media (max-width: 640px) {

  /* === "Six fields, no theatrics" list ===
     The <li> uses inline 80px 200px 1fr grid — 280px of label
     before any description, leaving ~95px for body text on phone.
     Stack the rows: §Nº + field name on top row, description
     underneath, with a hairline between items. */
  #submit-what ol li {
    display: grid !important;
    grid-template-columns: 48px 1fr !important;
    grid-template-rows: auto auto !important;
    column-gap: 12px !important;
    row-gap: 4px !important;
    padding: 16px 0 !important;
  }
  #submit-what ol li > span:nth-child(1) {
    /* § Nº — gilt monospace */
    grid-row: 1 !important;
    grid-column: 1 !important;
    align-self: baseline !important;
    font-size: 11px !important;
    letter-spacing: 0.18em !important;
  }
  #submit-what ol li > span:nth-child(2) {
    /* Field name — italic */
    grid-row: 1 !important;
    grid-column: 2 !important;
    font-size: 22px !important;
    line-height: 1.2 !important;
  }
  #submit-what ol li > span:nth-child(3) {
    /* Description */
    grid-row: 2 !important;
    grid-column: 2 !important;
    font-size: 14px !important;
    line-height: 1.55 !important;
    margin-top: 4px !important;
  }
  /* Section heading tighter on phone */
  #submit-what h2 {
    font-size: clamp(34px, 9.5vw, 48px) !important;
    line-height: 1.05 !important;
    margin: 0 0 28px !important;
  }
  #submit-what {
    padding: 40px 16px !important;
  }

  /* === Review process — 4 step cards → swipe gallery === */
  .cfp-process-grid {
    display: flex !important;
    grid-template-columns: none !important;
    flex-direction: row !important;
    overflow-x: auto !important;
    overflow-y: visible !important;
    scroll-snap-type: x mandatory;
    padding: 4px 16px 24px !important;
    margin: 0 -16px !important;
    gap: 14px !important;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .cfp-process-grid::-webkit-scrollbar { display: none; }
  .cfp-process-grid > * {
    flex: 0 0 80% !important;
    min-width: 0 !important;
    max-width: 80% !important;
    scroll-snap-align: start;
  }
  .cfp-process-grid::after {
    content: 'swipe →';
    flex: 0 0 auto !important;
    align-self: center !important;
    padding: 6px 12px !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 9.5px !important;
    letter-spacing: 0.22em !important;
    text-transform: uppercase !important;
    background: rgba(40,28,12,0.85) !important;
    color: #F4ECDA !important;
    border-radius: 14px !important;
    pointer-events: none !important;
    display: inline-flex !important;
    height: 28px;
    align-items: center;
  }

  /* === Review process h2 + container padding === */
  #process {
    padding: 40px 16px !important;
  }
  #process h2 {
    font-size: clamp(34px, 9.5vw, 48px) !important;
    line-height: 1.05 !important;
    margin: 0 0 28px !important;
  }
}


/* ============================================================
   CFP — Tracks section header layout (phone)
   ============================================================ */
@media (max-width: 640px) {
  /* The "§ I — The Tracks" + subline + H2 + paragraph should
     stack cleanly with breathing space, not crowd each other.
     Also: drop the hard <br> in the H2 markup by overriding it. */
  .cfp-where .stamp-row,
  section#tracks .stamp-row,
  section[id*="tracks"] .stamp-row {
    margin-bottom: 18px !important;
  }
  /* The H2 "Where your work belongs." has an inline <br> between
     "Where your" and "work belongs". On phone we want it to wrap
     naturally based on container width — hide the <br>. */
  section h2 br,
  section#tracks h2 br,
  section[id*="tracks"] h2 br {
    display: none !important;
  }
  /* Heading tighter and with proper margin below */
  section[id*="tracks"] h2,
  .cfp-where h2 {
    font-size: clamp(34px, 10vw, 48px) !important;
    line-height: 1.05 !important;
    letter-spacing: -0.025em !important;
    margin: 0 0 18px !important;
    text-wrap: balance;
  }
  /* The intro paragraph below the H2 — give it breathing space
     and don't let it crowd the heading. */
  section[id*="tracks"] > div > p,
  section[id*="tracks"] p:first-of-type {
    margin-top: 0 !important;
    margin-bottom: 24px !important;
    font-size: 15px !important;
    line-height: 1.55 !important;
  }
}


/* ============================================================
   CFP — Tracks section-header collapse (phone)
   ============================================================ */
@media (max-width: 640px) {
  /* The #tracks .section-header is INLINE-STYLED as a 2-col grid
     (heading | paragraph) — that pushes the intro paragraph next
     to the H2 on phone. Force single column so the paragraph
     sits underneath the heading. Same pattern likely appears on
     other section headers. */
  #tracks .section-header,
  section .section-header[style*="grid-template-columns: 1fr 1fr"],
  section [style*="display:grid"][style*="1fr 1fr"]:has(h2),
  section [style*="display:grid"][style*="1fr 1fr"]:has(> p) {
    display: block !important;
    grid-template-columns: 1fr !important;
    gap: 16px !important;
    margin-bottom: 32px !important;
  }
  #tracks .section-header > div + p,
  #tracks .section-header p {
    margin-top: 18px !important;
    max-width: 100% !important;
  }
}


/* ============================================================
   REGISTER PAGE — sticky bottom bar, tab strip, quick-pick,
   FAQ accordion (all phone-only)
   ============================================================ */
@media (max-width: 640px) {

  /* === 01 · STICKY RESERVE BAR (injected on register pages) === */
  .reg-mobile-stickybar {
    display: none; /* shown only on .register-page below */
  }
  body.register-page .reg-mobile-stickybar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 88;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
    background: rgba(244, 236, 218, 0.96);
    border-top: 1px solid var(--rule-2, rgba(40,28,12,0.22));
    box-shadow: 0 -8px 18px -8px rgba(40,28,12,0.18);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    transform: translateY(120%);
    transition: transform 320ms cubic-bezier(.22,.61,.36,1);
    pointer-events: auto;
  }
  body.register-page.show-stickybar .reg-mobile-stickybar {
    transform: translateY(0);
  }
  .reg-stickybar-info {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    flex: 1 1 auto;
  }
  .reg-stickybar-eyebrow {
    font-family: 'JetBrains Mono', monospace;
    font-size: 9.5px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--gilt, #B68A3E);
  }
  .reg-stickybar-price {
    font-family: 'Newsreader', Georgia, serif;
    font-style: italic;
    font-size: 18px;
    line-height: 1;
    color: var(--ink, #1A1208);
  }
  .reg-stickybar-cta {
    flex: 0 0 auto;
    background: linear-gradient(135deg, #C99A47 0%, #B68A3E 50%, #8a6620 100%);
    color: #FBF5E5;
    text-decoration: none;
    padding: 12px 18px;
    border-radius: 3px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    font-weight: 600;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    box-shadow: 0 2px 0 #6f5117, 0 6px 14px -3px rgba(40,28,12,0.35);
  }
  body.register-page.show-stickybar { padding-bottom: 80px; }

  /* === 02 · SECTION TAB STRIP (injected under page-header) === */
  .reg-mobile-tabstrip {
    display: none;
  }
  body.register-page .reg-mobile-tabstrip {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    overflow-y: visible;
    padding: 12px 16px;
    margin: 0 -16px 4px;
    border-top: 1px solid rgba(40,28,12,0.08);
    border-bottom: 1px solid rgba(40,28,12,0.08);
    background: rgba(244, 236, 218, 0.55);
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    position: sticky;
    top: 56px; /* under the compressed topnav */
    z-index: 70;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
  }
  body.register-page .reg-mobile-tabstrip::-webkit-scrollbar { display: none; }
  .reg-mobile-tab {
    flex: 0 0 auto;
    padding: 7px 14px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 10.5px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--muted, #6B5A36);
    background: transparent;
    border: 1px solid var(--rule-2, rgba(40,28,12,0.18));
    border-radius: 20px;
    text-decoration: none;
    transition: background 160ms ease, color 160ms ease, border-color 160ms ease;
    white-space: nowrap;
  }
  .reg-mobile-tab:active,
  .reg-mobile-tab.is-active {
    background: var(--ink, #1A1208);
    color: var(--paper, #FBF5E5);
    border-color: var(--ink, #1A1208);
  }

  /* === 03 · QUICK-PICK ROW (injected above tier swipe) === */
  .reg-mobile-quickpick {
    display: none;
  }
  body.register-page .reg-mobile-quickpick {
    display: flex;
    flex-direction: column;
    background: rgba(244, 236, 218, 0.55);
    border: 1px solid var(--rule-2, rgba(40,28,12,0.18));
    border-radius: 4px;
    padding: 4px 0;
    margin: 0 0 16px;
  }
  .reg-mobile-quickpick-row {
    display: grid;
    grid-template-columns: 1fr auto auto;
    align-items: baseline;
    gap: 14px;
    padding: 14px 16px;
    text-decoration: none;
    color: var(--ink, #1A1208);
    border-bottom: 1px solid rgba(40,28,12,0.08);
    transition: background 140ms ease;
  }
  .reg-mobile-quickpick-row:last-child {
    border-bottom: 0;
  }
  .reg-mobile-quickpick-row:active {
    background: rgba(229, 199, 122, 0.16);
  }
  .reg-mobile-qp-name {
    font-family: 'Newsreader', Georgia, serif;
    font-style: italic;
    font-size: 17px;
    line-height: 1.2;
  }
  .reg-mobile-qp-price {
    font-family: 'Newsreader', Georgia, serif;
    font-size: 18px;
    color: var(--ink, #1A1208);
    white-space: nowrap;
  }
  .reg-mobile-qp-arrow {
    color: var(--gilt, #B68A3E);
    font-size: 14px;
  }
  .reg-mobile-quickpick-foot {
    padding: 8px 16px 10px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 9.5px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--muted, #6B5A36);
    border-top: 1px solid rgba(40,28,12,0.08);
    text-align: center;
  }

  /* === 04 · FAQ ACCORDION === */
  .faq-item {
    border-bottom: 1px solid var(--rule-2, rgba(40,28,12,0.14));
    padding: 0 !important;
    margin: 0;
  }
  .faq-item h4 {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 18px 0 18px;
    margin: 0;
    cursor: pointer;
    font-size: 16px;
    line-height: 1.35;
    color: var(--ink);
    user-select: none;
    list-style: none;
  }
  .faq-item h4::after {
    content: '+';
    flex: 0 0 auto;
    width: 28px;
    height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--rule-2, rgba(40,28,12,0.22));
    border-radius: 50%;
    font-family: 'JetBrains Mono', monospace;
    font-size: 16px;
    color: var(--gilt, #B68A3E);
    transition: transform 220ms ease, background 220ms ease;
  }
  .faq-item.is-open h4::after {
    content: '−';
    background: var(--ink);
    color: var(--paper);
    border-color: var(--ink);
  }
  .faq-item > p,
  .faq-item > a,
  .faq-item > .visa-letter-btn {
    max-height: 0;
    overflow: hidden;
    opacity: 0;
    margin: 0 !important;
    padding: 0 !important;
    transition: max-height 320ms ease, opacity 220ms ease, padding 220ms ease, margin 220ms ease;
  }
  .faq-item.is-open > p,
  .faq-item.is-open > a,
  .faq-item.is-open > .visa-letter-btn {
    max-height: 800px;
    opacity: 1;
    padding: 0 0 18px !important;
    margin: 0 0 0 !important;
  }
  .faq-item.is-open > .visa-letter-btn {
    margin-top: 8px !important;
    margin-bottom: 18px !important;
    padding: 14px 16px !important;
  }
}


/* ============================================================
   REGISTER PAGE HEADER — illustrations centered on phone
   ============================================================ */
@media (max-width: 640px) {
  /* Page-header decorative sketches are absolute-positioned on
     desktop with negative left offsets to peek into the heading
     column. On phone that negative offset shoves them off-screen
     to the left. Reset to centered flow positioning. */
  .page-header-sketch {
    position: relative !important;
    left: auto !important;
    right: auto !important;
    top: auto !important;
    bottom: auto !important;
    transform: none !important;
    margin: 18px auto !important;
    width: min(220px, 70vw) !important;
    max-width: 100% !important;
    display: block !important;
  }
  .page-header-sketch svg,
  .page-header-sketch .sk-svg {
    width: 100% !important;
    height: auto !important;
    max-width: 100% !important;
    display: block !important;
  }
  /* When multiple sketches exist (e.g. ticket + secondary motif on
     the register page), stack them centered below the heading. */
  .page-header-sketches {
    display: flex !important;
    flex-direction: column !important;
    align-items: center !important;
    gap: 12px !important;
    grid-template-columns: none !important;
    padding: 0 !important;
    margin: 12px auto 0 !important;
  }
}


/* ============================================================
   REGISTER — price windows + cancel band (phone)
   ============================================================ */
@media (max-width: 640px) {

  /* === Price-window rows ===
     Each .pw has [.pw-k label] [.pw-d date] [.pw-v €price] which
     on desktop sits as a 3-col grid. On phone the column widths
     are inconsistent so the €330 / €410 / €510 don't line up
     vertically. Force a fixed-width price column on the right
     so all three €values line up in a clean column. */
  .ticket .price-windows {
    display: flex !important;
    flex-direction: column !important;
    gap: 10px !important;
    margin: 16px 0 !important;
  }
  .ticket .pw {
    display: grid !important;
    grid-template-columns: 1fr auto !important;
    grid-template-rows: auto auto !important;
    align-items: baseline !important;
    column-gap: 14px !important;
    row-gap: 2px !important;
    padding: 10px 0 !important;
    border-bottom: 1px solid rgba(40,28,12,0.10) !important;
  }
  .ticket .pw:last-child { border-bottom: 0 !important; }
  .ticket .pw .pw-k {
    grid-row: 1 !important;
    grid-column: 1 !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10.5px !important;
    letter-spacing: 0.18em !important;
    text-transform: uppercase !important;
    color: var(--ink) !important;
  }
  .ticket .pw .pw-d {
    grid-row: 2 !important;
    grid-column: 1 !important;
    font-family: 'Newsreader', Georgia, serif !important;
    font-style: italic !important;
    font-size: 13px !important;
    color: var(--muted, #6B5A36) !important;
    line-height: 1.4 !important;
  }
  .ticket .pw .pw-v {
    grid-row: 1 / 3 !important;
    grid-column: 2 !important;
    align-self: center !important;
    justify-self: end !important;
    font-family: 'Newsreader', Georgia, serif !important;
    font-weight: 300 !important;
    font-size: 30px !important;
    line-height: 1 !important;
    color: var(--ink) !important;
    /* Fixed-width column so €330 / €410 / €510 line up vertically. */
    min-width: 70px !important;
    text-align: right !important;
  }
  .ticket .pw .pw-v .cur {
    font-size: 0.7em !important;
    margin-right: 1px !important;
    vertical-align: 1px !important;
    color: var(--gilt, #B68A3E) !important;
  }
  /* Override the desktop "Early Bird gets bigger" treatment — on
     phone all three windows read the same size for clean alignment. */
  .ticket .price-windows .pw:first-child .pw-v,
  .ticket.featured .price-windows .pw:first-child .pw-v {
    font-size: 30px !important;
  }

  /* === Cancellation band ===
     The .reg-cancel-band shows three policies separated by ·
     bullets. On phone they collide. Stack each policy on its own
     line with a small caps "WHAT IT COVERS" label. */
  .reg-cancel-band {
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 8px !important;
    padding: 16px 16px !important;
    margin: 24px 0 !important;
  }
  .reg-cancel-band .reg-cancel-stamp {
    margin-bottom: 4px !important;
  }
  /* The body text inside is currently one inline string with
     middle-dot separators. Use a CSS hack to break before each ·
     to give each policy its own line. */
  .reg-cancel-band .reg-cancel-body,
  .reg-cancel-band > span:not(.reg-cancel-stamp) {
    display: block !important;
    font-size: 14px !important;
    line-height: 1.55 !important;
  }
}


/* ============================================================
   REGISTER — cancel-band split lines (phone)
   ============================================================ */
@media (max-width: 640px) {
  .reg-cancel-band .reg-cancel-line {
    display: block !important;
    padding: 2px 0 !important;
    line-height: 1.5 !important;
  }
  /* Add a small gilt bullet before each line for editorial polish */
  .reg-cancel-band .reg-cancel-line::before {
    content: '·';
    color: var(--gilt, #B68A3E);
    margin-right: 8px;
    font-weight: 600;
  }
}


/* ============================================================
   CANCEL-BAND — proper line breaks via separator span (phone)
   ============================================================ */
@media (max-width: 640px) {
  /* The .reg-cancel-lines wrapper has inline content broken up by
     <span class="reg-cancel-sep">·</span>. Make the wrapper preserve
     whitespace and turn each separator into a hard newline + a gilt
     bullet on the next line. */
  .reg-cancel-band .reg-cancel-lines {
    display: block !important;
    white-space: normal !important;
    line-height: 1.6 !important;
  }
  .reg-cancel-band .reg-cancel-sep {
    display: block !important;
    width: 100% !important;
    height: 0 !important;
    overflow: hidden !important;
    margin: 4px 0 0 0 !important;
    font-size: 0 !important;
    line-height: 0 !important;
    color: transparent !important;
  }
  /* After each separator, the next <em> reads as the start of a new
     policy line — give it a small gilt bullet for editorial polish. */
  .reg-cancel-band .reg-cancel-sep + em::before {
    content: '· ';
    color: var(--gilt, #B68A3E);
    margin-right: 2px;
  }
  /* Also the first em gets a leading bullet for consistency */
  .reg-cancel-band .reg-cancel-lines > em:first-of-type::before {
    content: '· ';
    color: var(--gilt, #B68A3E);
    margin-right: 2px;
  }
}


/* ============================================================
   PROGRAMME PAGE — mobile layout (defensive only, page has its
   own comprehensive mobile schedule CSS we shouldn't override)
   ============================================================ */
@media (max-width: 640px) {

  /* === SPEAKER PLATE WALL — 3-col instead of 4 === */
  section .fn-wall,
  .fn-wall {
    grid-template-columns: repeat(3, 1fr) !important;
    gap: 10px !important;
  }
  .fn-tile {
    aspect-ratio: 1 / 1 !important;
    min-height: 90px !important;
  }
  .fn-tile-name {
    font-size: 11.5px !important;
    line-height: 1.3 !important;
  }
  .fn-tile-plate {
    font-size: 10px !important;
  }

  /* === SECTION HEADING OVERFLOW ===
     .fn-stamp / .fn-h / .fn-meta have desktop `white-space: nowrap`
     that pushes them 18px past the right edge at 343px content
     width. Allow wrap. */
  .fn-stamp,
  .fn-h,
  .fn-meta,
  .programme .fn-stamp,
  .programme .fn-h,
  .programme .fn-meta {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    white-space: normal !important;
  }

  /* === DAY TABS / DAY BLOCKS — sticky for scroll context === */
  .day-tabs {
    position: sticky;
    top: 56px;
    background: var(--paper, #FBF5E5);
    z-index: 14;
    padding: 8px 0;
    overflow-x: auto;
    white-space: nowrap;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    box-shadow: 0 1px 0 var(--rule-2, rgba(40,28,12,0.08));
  }
  .day-tabs::-webkit-scrollbar { display: none; }
  /* Day-block <summary> already sticky-friendly via the page's own CSS */

  /* === SCHEDULE TYPE on phone — make sure type doesn't shrink to
     unreadable inside the existing 1-col stacked schedule. The
     page's own CSS uses font-size 22px on h3 and 14.5px on p
     for stacked mode — keep those, just enforce. */
  .schedule[data-mode="all"] .session > .body h3,
  .schedule[data-mode="filtered"] .session > .body h3 {
    font-size: 18px !important;
    line-height: 1.25 !important;
  }
  .schedule[data-mode="all"] .session > .body p,
  .schedule[data-mode="filtered"] .session > .body p {
    font-size: 14px !important;
    line-height: 1.5 !important;
  }
  .schedule[data-mode="all"] .session > .time,
  .schedule[data-mode="filtered"] .session > .time {
    font-size: 13px !important;
  }
}


/* ============================================================
   PROGRAMME SCHEDULE — FORCE READABLE STACK (phone)
   The page's existing mobile CSS uses display:contents which on
   the 4-track grid produces an unreadable wall. Override hard:
   every session becomes a single-column paper card with clear
   borders, gilt eyebrow (time + room), italic title, speaker.
   ============================================================ */
@media (max-width: 640px) {

  /* === SCHEDULE — single-column stack === */
  .schedule,
  .schedule[data-mode="all"],
  .schedule[data-mode="filtered"] {
    display: block !important;
    grid-template-columns: none !important;
    background-image: none !important;
    padding: 0 !important;
  }

  /* === SESSION — undo display:contents, render as card === */
  .schedule .session,
  .schedule[data-mode="all"] .session,
  .schedule[data-mode="filtered"] .session,
  .day-block .session {
    display: grid !important;
    grid-template-columns: 1fr !important;
    grid-template-rows: auto auto auto !important;
    grid-template-areas: "eyebrow" "title" "speaker" !important;
    gap: 4px !important;
    padding: 14px 14px 16px !important;
    margin: 0 0 8px !important;
    background: rgba(244, 236, 218, 0.55) !important;
    border: 1px solid rgba(40, 28, 12, 0.10) !important;
    border-radius: 4px !important;
    box-shadow: none !important;
  }

  /* === SESSION CHILDREN (.time, .body, .meta) ===
     These were absolute-positioned into the grid. Now they're
     children of a card and need to render in their assigned area. */
  .schedule .session > .time,
  .schedule[data-mode="all"] .session > .time,
  .schedule[data-mode="filtered"] .session > .time {
    grid-area: eyebrow !important;
    grid-column: auto !important;
    grid-row: auto !important;
    display: inline-block !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 11px !important;
    letter-spacing: 0.18em !important;
    text-transform: uppercase !important;
    color: var(--gilt, #B68A3E) !important;
    border: none !important;
    padding: 0 !important;
    background: none !important;
    margin: 0 !important;
    visibility: visible !important;
  }
  .schedule .session > .meta,
  .schedule[data-mode="all"] .session > .meta,
  .schedule[data-mode="filtered"] .session > .meta {
    grid-area: eyebrow !important;
    grid-column: auto !important;
    grid-row: auto !important;
    display: inline-flex !important;
    justify-self: end !important;
    align-self: center !important;
    gap: 6px !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 9.5px !important;
    letter-spacing: 0.18em !important;
    text-transform: uppercase !important;
    color: var(--muted, #6B5A36) !important;
    padding: 0 !important;
    background: none !important;
    margin: 0 !important;
  }
  /* Place time on left, meta on right of the eyebrow row */
  .schedule .session,
  .schedule[data-mode="all"] .session,
  .schedule[data-mode="filtered"] .session {
    grid-template-columns: auto 1fr !important;
    grid-template-rows: auto auto auto !important;
    grid-template-areas:
      "time meta"
      "title title"
      "speaker speaker" !important;
  }
  .schedule .session > .time,
  .schedule[data-mode="all"] .session > .time,
  .schedule[data-mode="filtered"] .session > .time {
    grid-area: time !important;
  }
  .schedule .session > .meta,
  .schedule[data-mode="all"] .session > .meta,
  .schedule[data-mode="filtered"] .session > .meta {
    grid-area: meta !important;
  }
  /* Hide the "30 min" duration inside meta — already implied by time range */
  .schedule .session > .meta > span:not(.pill),
  .schedule[data-mode="all"] .session > .meta > span:not(.pill),
  .schedule[data-mode="filtered"] .session > .meta > span:not(.pill) {
    display: none !important;
  }
  /* The "Hall X · Track NN" pill — keep visible, clean styling */
  .schedule .session > .meta .pill,
  .schedule[data-mode="all"] .session > .meta .pill {
    background: none !important;
    border: none !important;
    padding: 0 !important;
    color: var(--muted, #6B5A36) !important;
    font-weight: 400 !important;
  }

  /* === SESSION BODY === */
  .schedule .session > .body,
  .schedule[data-mode="all"] .session > .body,
  .schedule[data-mode="filtered"] .session > .body {
    grid-area: title !important;
    grid-column: 1 / -1 !important;
    grid-row: auto !important;
    background: none !important;
    border: none !important;
    border-left: none !important;
    padding: 4px 0 0 !important;
    margin: 0 !important;
    box-shadow: none !important;
  }
  .schedule .session > .body::before {
    display: none !important;
  }
  .schedule .session > .body h3,
  .schedule[data-mode="all"] .session > .body h3,
  .schedule[data-mode="filtered"] .session > .body h3 {
    font-family: 'Newsreader', Georgia, serif !important;
    font-style: italic !important;
    font-weight: 400 !important;
    font-size: 18px !important;
    line-height: 1.25 !important;
    color: var(--ink, #1A1208) !important;
    margin: 0 0 6px !important;
  }
  .schedule .session > .body p,
  .schedule[data-mode="all"] .session > .body p,
  .schedule[data-mode="filtered"] .session > .body p {
    font-family: 'Newsreader', Georgia, serif !important;
    font-weight: 300 !important;
    font-size: 14.5px !important;
    line-height: 1.5 !important;
    color: var(--ink, #1A1208) !important;
    margin: 0 0 6px !important;
  }
  .schedule .session > .body .speaker,
  .schedule[data-mode="all"] .session > .body .speaker {
    grid-area: speaker !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10.5px !important;
    letter-spacing: 0.16em !important;
    text-transform: uppercase !important;
    color: var(--gilt, #B68A3E) !important;
    margin: 4px 0 0 !important;
    line-height: 1.5 !important;
  }

  /* === TBA / RESERVED SESSIONS — show all 4 tracks, but quieter ===
     In "All" mode the user wants to see all 4 tracks at each
     timeslot — even when most are TBA. Render confirmed sessions
     full-strength and TBA placeholders in muted style so the
     reader's eye lands on confirmed first. */
  .schedule .session.tba,
  .schedule[data-mode="all"] .session.tba,
  .schedule[data-mode="filtered"] .session.tba,
  .session[data-confirmed="false"] {
    display: grid !important;
    background: rgba(244, 236, 218, 0.30) !important;
    border-color: rgba(40, 28, 12, 0.06) !important;
    border-style: dashed !important;
    opacity: 0.78 !important;
  }
  .schedule .session.tba > .body h3,
  .schedule[data-mode="all"] .session.tba > .body h3,
  .session[data-confirmed="false"] > .body h3 {
    color: var(--muted, #6B5A36) !important;
    font-style: italic !important;
  }
  .schedule .session.tba > .body p,
  .schedule[data-mode="all"] .session.tba > .body p,
  .session[data-confirmed="false"] > .body p {
    color: var(--muted, #6B5A36) !important;
    opacity: 0.85 !important;
  }

  /* === BREAKS — render as a slim divider, not a full card === */
  .schedule .session.break,
  .schedule[data-mode="all"] .session.break,
  .schedule[data-mode="filtered"] .session.break {
    background: transparent !important;
    border: none !important;
    padding: 6px 14px !important;
    margin: 4px 0 !important;
    grid-template-areas: "time title" "time title" "time title" !important;
    grid-template-columns: auto 1fr !important;
  }
  .schedule .session.break > .body h3,
  .schedule[data-mode="all"] .session.break > .body h3 {
    font-family: 'JetBrains Mono', monospace !important;
    font-style: normal !important;
    font-size: 10.5px !important;
    letter-spacing: 0.18em !important;
    text-transform: uppercase !important;
    color: var(--muted, #6B5A36) !important;
    font-weight: 400 !important;
  }
  .schedule .session.break > .meta {
    display: none !important;
  }

  /* === KEYNOTE — slight highlight === */
  .schedule .session.keynote,
  .schedule[data-mode="all"] .session.keynote {
    background: rgba(229, 199, 122, 0.10) !important;
    border-color: rgba(182, 138, 62, 0.35) !important;
  }
  .schedule .session.keynote > .body h3 {
    font-size: 19px !important;
  }

  /* === TBA inside breaks etc — hide any "tba-stamp" decoration === */
  .session .tba-stamp,
  .session .tba-h,
  .session .tba-sub {
    display: none !important;
  }

  /* === DAY HEADER — comfortable padding === */
  .day-block > summary {
    padding: 18px 14px !important;
    gap: 14px !important;
    grid-template-columns: auto 1fr auto !important;
  }
  .day-block .day-num {
    font-size: 36px !important;
  }
  .day-block .day-name {
    font-size: 18px !important;
    line-height: 1.2 !important;
  }
  .day-block .day-date {
    font-size: 13px !important;
  }
  .day-block .schedule {
    padding: 14px 14px 28px !important;
  }
}


/* ============================================================
   SPEAKERS PAGE — mobile fixes
   ============================================================ */
@media (max-width: 640px) {

  /* === GUILD PILLS — chip strip overflowing ===
     The "guild-pill" filter buttons (probably "All guilds /
     Cryptographica / Fabricae / Iuris") had each pill at a
     fixed width that pushed siblings past the viewport.
     Convert to a horizontal swipe row that scrolls. */
  .guild-pills,
  [class*="guild-pills"],
  .guild-filter,
  [class*="guild-filter"] {
    display: flex !important;
    flex-wrap: nowrap !important;
    overflow-x: auto !important;
    gap: 8px !important;
    padding: 8px 16px !important;
    margin: 0 -16px !important;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .guild-pills::-webkit-scrollbar,
  [class*="guild-pills"]::-webkit-scrollbar { display: none; }
  .guild-pill,
  [class*="guild-pill"] {
    flex: 0 0 auto !important;
    width: auto !important;
    min-width: 0 !important;
    padding: 7px 14px !important;
    font-size: 10.5px !important;
    letter-spacing: 0.16em !important;
    white-space: nowrap !important;
  }

  /* === PLENARY TRIO swipe gallery ===
     The 3 plenary cards already swipe via earlier rule, but the
     cards were 118px wide — too narrow to read. Bump to 80%. */
  .ph-plenary-grid > .ph-plenary,
  .ph-plenary-grid > * {
    flex: 0 0 80% !important;
    max-width: 80% !important;
    min-width: 0 !important;
  }
  .ph-plenary-link {
    padding: 18px 16px !important;
  }
  .ph-plenary-name {
    font-size: 22px !important;
    line-height: 1.15 !important;
  }
  .ph-plenary-affil {
    font-size: 13px !important;
  }
  .ph-plenary-talk {
    font-size: 12px !important;
    line-height: 1.4 !important;
  }
  .ph-plenary-day {
    font-size: 10px !important;
    letter-spacing: 0.18em !important;
  }

  /* === ROSTER PLATE CARDS — flatten 5-col grid to stacked card ===
     Each .plate uses `grid-template-columns: 70px 56px 220px 220px
     0px` (566px wide in a 331px container — overflows internally).
     Force single column with portrait on top, name + affiliation
     stacked underneath. */
  .plate,
  article.plate {
    display: grid !important;
    grid-template-columns: 1fr !important;
    grid-template-rows: auto auto auto !important;
    grid-template-areas:
      "portrait"
      "name"
      "body" !important;
    gap: 8px !important;
    padding: 16px 14px !important;
    width: 100% !important;
    max-width: 100% !important;
  }
  /* The Roman numeral / plate number is decorative — keep it small
     in the corner. */
  .plate > .plate-num,
  .plate > .roman,
  .plate > .num,
  .plate > [class*="-num"]:not([class*="surface"]) {
    grid-area: name !important;
    grid-column: 1 !important;
    grid-row: 1 !important;
    font-size: 12px !important;
    color: var(--gilt, #B68A3E) !important;
    margin: 0 !important;
  }
  /* Portrait image — full width, max-height capped. */
  .plate img,
  .plate > .plate-portrait,
  .plate > [class*="portrait"] {
    grid-area: portrait !important;
    grid-column: 1 !important;
    grid-row: 1 !important;
    width: 100% !important;
    max-width: 100% !important;
    aspect-ratio: 4 / 5;
    object-fit: cover;
    height: auto !important;
  }
  /* Name + affil + guild label */
  .plate > .plate-name,
  .plate > .plate-h,
  .plate > h3,
  .plate > .name {
    grid-area: name !important;
    grid-column: 1 !important;
    font-family: 'Newsreader', Georgia, serif !important;
    font-style: italic !important;
    font-weight: 400 !important;
    font-size: 22px !important;
    line-height: 1.2 !important;
    margin: 0 !important;
  }
  .plate > .plate-affil,
  .plate > .plate-body,
  .plate > [class*="affil"],
  .plate > p {
    grid-area: body !important;
    grid-column: 1 !important;
    font-family: 'Newsreader', Georgia, serif !important;
    font-size: 14px !important;
    line-height: 1.4 !important;
    color: var(--muted, #6B5A36) !important;
    margin: 0 !important;
  }
}

/* ============================================================
   SPEAKER DETAIL PAGE — mobile fixes
   ============================================================ */
@media (max-width: 640px) {
  /* The sp-hero grid (portrait | body) was desktop 2-col.
     Already handled by earlier .sp-hero rule. Make sure portrait
     stays a sensible size. */
  .sp-hero {
    display: block !important;
    grid-template-columns: 1fr !important;
  }
  .sp-portrait,
  .sp-portrait img,
  .sp-photo,
  .sp-photo img {
    width: 100% !important;
    max-width: min(300px, 70vw) !important;
    margin: 0 auto 20px !important;
    display: block;
    height: auto !important;
  }
  .sp-name,
  .sp-h,
  .speaker-name {
    font-size: clamp(32px, 9vw, 44px) !important;
    line-height: 1.05 !important;
    text-align: left;
  }
  /* Talk title — italic, secondary level */
  .sp-talk-title,
  .speaker-talk-title,
  .sp-hero h2 {
    font-size: clamp(20px, 5.5vw, 26px) !important;
    line-height: 1.2 !important;
  }
}


/* ============================================================
   CFP SCARCITY BANNER — push below topnav on phone
   ============================================================ */
@media (max-width: 640px) {
  /* The CFP banner sits below the fixed topnav. The topnav on phone
     is ~56-73px tall, so the banner needs that much top spacing or
     it gets clipped under the nav. Also tighten its own padding so
     the message reads in 2 lines max. */
  .cfp-banner,
  [class*="cfp-banner"]:not([class*="-inner"]) {
    margin-top: 73px !important;
    padding: 10px 14px !important;
  }
  .cfp-banner-inner {
    grid-template-columns: 1fr !important;
    gap: 8px !important;
    padding: 0 !important;
    text-align: center !important;
  }
  .cfp-banner-inner .stamp,
  .cfp-banner-inner [class*="stamp"] {
    font-size: 10px !important;
    letter-spacing: 0.22em !important;
  }
  .cfp-banner-inner .headline,
  .cfp-banner-inner [class*="headline"] {
    font-size: 13px !important;
    line-height: 1.4 !important;
    white-space: normal !important;
  }
  .cfp-banner-inner .meta,
  .cfp-banner-inner [class*="meta"] {
    font-size: 11px !important;
    line-height: 1.4 !important;
  }
  /* Compensate the topnav offset — the page-header below the banner
     no longer needs its own topnav-clearance padding when the banner
     already provides one. */
  .cfp-banner + .page-header,
  .cfp-banner + main,
  .cfp-banner + section {
    margin-top: 0 !important;
  }
}


/* ============================================================
   SPEAKERS PAGE — comprehensive mobile polish
   ============================================================ */
@media (max-width: 640px) {

  /* === 01 · PLENARY TRIO swipe gallery (full pattern) ===
     Three plenary cards convert to horizontal swipe. */
  .ph-plenary-grid,
  .ph-plenary-stack {
    display: flex !important;
    grid-template-columns: none !important;
    flex-direction: row !important;
    overflow-x: auto !important;
    overflow-y: visible !important;
    scroll-snap-type: x mandatory;
    padding: 4px 16px 24px !important;
    margin: 0 -16px !important;
    gap: 14px !important;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .ph-plenary-grid::-webkit-scrollbar,
  .ph-plenary-stack::-webkit-scrollbar { display: none; }
  .ph-plenary-grid > .ph-plenary,
  .ph-plenary-stack > .ph-plenary,
  .ph-plenary-grid > * {
    flex: 0 0 82% !important;
    max-width: 82% !important;
    min-width: 0 !important;
    scroll-snap-align: start;
  }
  .ph-plenary-grid::after,
  .ph-plenary-stack::after {
    content: 'swipe →';
    flex: 0 0 auto !important;
    align-self: center !important;
    padding: 6px 12px !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 9.5px !important;
    letter-spacing: 0.22em !important;
    text-transform: uppercase !important;
    background: rgba(40,28,12,0.85) !important;
    color: #F4ECDA !important;
    border-radius: 14px !important;
    height: 28px;
    display: inline-flex !important;
    align-items: center !important;
    pointer-events: none !important;
  }

  /* === 02 · HIDE "Coming soon" placeholder lines ===
     When the talk title is still TBA, the placeholder text is
     editorially repetitive on mobile. Hide it. */
  .ph-plenary-talk em:only-child,
  .ph-plenary-talk:has(em:only-child),
  .ph-plenary .ph-plenary-talk[data-placeholder="true"] {
    /* keep one — hide the second */
  }
  /* Hide the talk-title line entirely when its only content is
     italic "Coming soon" — placeholder noise. */
  .ph-plenary-talk {
    display: none !important;
  }
  /* If you want to keep the "Coming soon" cue visible for SOME
     state, remove the rule above and add a single-line italic
     placeholder treatment. */

  /* === 03 · HIDE "See the full roster ↓" link on phone ===
     The roster sits directly below the trio anyway — the link is
     redundant. */
  .ph-plenary-foot,
  a.ph-plenary-foot,
  [class*="see-full-roster"],
  a[href$="#speakers"]:not(.btn):not([class*="topnav"]) {
    display: none !important;
  }

  /* === 04 · ROSTER as 2-col compact tile grid ===
     The 15 plate cards stacked vertically = long scroll. Render
     as 2-col compact tiles: portrait fills the card, italic name
     beneath, tap-target = entire card. */
  .plates,
  [class*="plates-grid"],
  section[id="speakers"] .plates,
  .sp-roster {
    display: grid !important;
    grid-template-columns: repeat(2, 1fr) !important;
    gap: 12px !important;
    padding: 0 !important;
  }
  .plate,
  article.plate {
    display: grid !important;
    grid-template-columns: 1fr !important;
    grid-template-rows: auto auto auto !important;
    grid-template-areas: "portrait" "name" "affil" !important;
    gap: 6px !important;
    padding: 10px !important;
    background: rgba(244, 236, 218, 0.55) !important;
    border: 1px solid rgba(40, 28, 12, 0.12) !important;
    border-radius: 4px !important;
    width: 100% !important;
    max-width: 100% !important;
  }
  .plate img,
  .plate [class*="portrait"] {
    grid-area: portrait !important;
    grid-column: 1 !important;
    grid-row: auto !important;
    width: 100% !important;
    max-width: 100% !important;
    aspect-ratio: 4 / 5 !important;
    object-fit: cover !important;
    height: auto !important;
    border-radius: 2px;
  }
  .plate > .name,
  .plate > h3,
  .plate > [class*="name"]:not([class*="num"]) {
    grid-area: name !important;
    grid-column: 1 !important;
    font-family: 'Newsreader', Georgia, serif !important;
    font-style: italic !important;
    font-weight: 400 !important;
    font-size: 15px !important;
    line-height: 1.15 !important;
    margin: 4px 0 0 !important;
  }
  .plate > .affil,
  .plate > [class*="affil"],
  .plate > p,
  .plate > .place {
    grid-area: affil !important;
    grid-column: 1 !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 9.5px !important;
    letter-spacing: 0.14em !important;
    text-transform: uppercase !important;
    color: var(--muted, #6B5A36) !important;
    line-height: 1.4 !important;
    margin: 2px 0 0 !important;
  }
  .plate > [class*="num"],
  .plate > .roman,
  .plate > .plate-num {
    /* Roman numeral — small corner stamp */
    position: absolute;
    top: 6px;
    right: 8px;
    font-size: 10px !important;
    color: var(--gilt, #B68A3E) !important;
    margin: 0 !important;
    padding: 0 !important;
  }
  .plate {
    position: relative !important;
  }
  /* Hide any guild label inside the plate — already conveyed by
     the filter chip strip above. */
  .plate > .guild,
  .plate > [class*="guild"],
  .plate > .latin {
    display: none !important;
  }
}


/* ============================================================
   PLENARY CARD — fix portrait/body 80px+0px grid collapse (phone)
   ============================================================ */
@media (max-width: 640px) {
  /* The .ph-plenary-link uses a 2-col grid (portrait | body) with
     the body column collapsed to 0px on phone (the desktop track
     pattern doesn't fit at narrow widths). Stack vertically. */
  .ph-plenary-link {
    display: grid !important;
    grid-template-columns: 1fr !important;
    grid-template-rows: auto auto !important;
    gap: 12px !important;
    padding: 14px !important;
  }
  .ph-plenary-portrait {
    width: 100% !important;
    max-width: 160px !important;
    margin: 0 auto !important;
    aspect-ratio: 1 / 1;
  }
  .ph-plenary-portrait img {
    width: 100% !important;
    height: 100% !important;
    object-fit: cover !important;
    border-radius: 2px;
  }
  .ph-plenary-body {
    width: 100% !important;
    min-width: 0 !important;
    text-align: center !important;
    padding: 0 !important;
  }
}


/* ============================================================
   SPEAKERS PAGE — fix swipe overlap + hide side-rail meta
   ============================================================ */
@media (max-width: 640px) {
  /* (Previously hid the .ph-plenary-grid swipe chip — restored below
     by the unified sticky-hint rule at the end of this file so users
     see "swipe →" on every horizontal-scroll row from the start.) */

  /* === Side-rail meta info that leaked into main content ===
     "ROSTER / NEW NAMES ADDED MONTHLY THROUGH JULY / CFP CLOSES /
     15 JUNE 2026 / KEYNOTES / THREE ACROSS THREE DAYS" — this is
     a desktop side-rail that appears in the page flow on mobile.
     Hide it on phone since the info is duplicated in the page
     content below. */
  .sp-rail,
  aside.sp-rail,
  [class*="sp-rail"],
  .speakers-rail,
  [class*="speakers-rail"],
  .roster-meta-rail,
  .sp-aside,
  .sp-foot-rail,
  aside[class*="rail"]:not(.scroll-rail) {
    display: none !important;
  }
}


/* ============================================================
   PAGE-HEADER META strip (Roster · CFP closes · Keynotes etc) (phone)
   ============================================================ */
@media (max-width: 640px) {
  /* The .page-header-meta strip renders below the heading as a
     row of key/value items. On phone they collapse into a tight
     stack of label + value rows. Was leaking as floating text
     because each .item had no styling separator on phone. */
  .page-header-inner.page-header-meta,
  .page-header-meta {
    display: flex !important;
    flex-direction: column !important;
    gap: 0 !important;
    grid-template-columns: none !important;
    padding: 16px 0 !important;
    margin: 18px 0 0 !important;
    border-top: 1px solid var(--rule-2, rgba(40,28,12,0.14)) !important;
    border-bottom: 1px solid var(--rule-2, rgba(40,28,12,0.14)) !important;
  }
  .page-header-meta .item {
    display: grid !important;
    grid-template-columns: 1fr auto !important;
    column-gap: 14px !important;
    padding: 10px 0 !important;
    border-bottom: 1px solid rgba(40, 28, 12, 0.08) !important;
    align-items: baseline !important;
  }
  .page-header-meta .item:last-child {
    border-bottom: 0 !important;
  }
  .page-header-meta .k {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10px !important;
    letter-spacing: 0.18em !important;
    text-transform: uppercase !important;
    color: var(--muted, #6B5A36) !important;
    line-height: 1.4 !important;
  }
  .page-header-meta .v {
    font-family: 'Newsreader', Georgia, serif !important;
    font-style: italic !important;
    font-size: 14px !important;
    color: var(--ink, #1A1208) !important;
    line-height: 1.3 !important;
    text-align: right !important;
  }
}


/* ============================================================
   SPEAKERS PAGE — page-header-inner grid stack + plenary card
   layout (phone)
   ============================================================ */
@media (max-width: 640px) {
  /* The .page-header-inner on speakers.html is a 2-col grid with
     the heading + plenary trio on LEFT and the meta key/value
     strip on RIGHT (Roster / CFP closes / Keynotes / Format).
     On phone both columns were forced into the same grid track
     so the meta-strip rendered ON TOP of the plenary cards. Force
     single column so meta sits BELOW the trio. */
  header.page-header .page-header-inner,
  .page-header > .page-header-inner,
  .speakers .page-header-inner {
    display: block !important;
    grid-template-columns: 1fr !important;
    column-gap: 0 !important;
    row-gap: 24px !important;
  }
  header.page-header .page-header-inner > * {
    width: 100% !important;
    max-width: 100% !important;
  }
  /* Force the meta strip to sit AFTER the heading + trio, not
     overlap them. */
  .page-header-inner + .page-header-inner,
  .page-header-inner.page-header-meta {
    margin-top: 18px !important;
    position: static !important;
  }

  /* === PLENARY CARD — corner-bracket frame on phone ===
     The desktop card uses an absolute-positioned corner-bracket
     SVG frame around the content. On phone with content stacked
     vertically, the bracket frame doesn't fit the new height.
     Just hide the decorative frame on phone — cleaner card. */
  .ph-plenary .ph-plenary-frame,
  .ph-plenary [class*="frame"],
  .ph-plenary [class*="corner"],
  .ph-plenary svg[viewBox] {
    display: none !important;
  }
  /* Tighten the card so it's a single coherent block */
  .ph-plenary {
    padding: 0 !important;
  }
  .ph-plenary-link {
    padding: 18px 16px !important;
    text-align: center !important;
    border: 1px solid rgba(40, 28, 12, 0.14) !important;
    border-radius: 4px !important;
    background: rgba(244, 236, 218, 0.55) !important;
  }
  .ph-plenary-day {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10px !important;
    letter-spacing: 0.22em !important;
    text-transform: uppercase !important;
    color: var(--gilt, #B68A3E) !important;
    margin: 0 0 10px !important;
    display: block !important;
  }
  .ph-plenary-portrait {
    width: 100px !important;
    height: 100px !important;
    max-width: 100px !important;
    margin: 0 auto 12px !important;
    aspect-ratio: 1 / 1 !important;
    border-radius: 50% !important;
    overflow: hidden !important;
  }
  .ph-plenary-portrait img {
    border-radius: 50% !important;
  }
  .ph-plenary-name {
    font-family: 'Newsreader', Georgia, serif !important;
    font-style: italic !important;
    font-weight: 400 !important;
    font-size: 22px !important;
    line-height: 1.15 !important;
    color: var(--ink, #1A1208) !important;
    margin: 0 0 6px !important;
  }
  .ph-plenary-affil {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10.5px !important;
    letter-spacing: 0.14em !important;
    text-transform: uppercase !important;
    color: var(--muted, #6B5A36) !important;
    margin: 0 !important;
    line-height: 1.4 !important;
  }
}


/* ============================================================
   PAGE-HEADER SKETCH — let it grow on phone (was 180×240 fixed)
   ============================================================ */
@media (max-width: 640px) {
  /* The page-header sketches had a fixed 180×240 box on phone via
     the page's own @media rule. For the .ph-plenary-slot (which
     holds the trio of plenary cards stacked vertically) that's
     ~half the height needed — cards overflow the slot and crash
     into the meta strip below. Reset height to auto + full width
     for the plenary slot specifically. */
  .page-header-sketch.ph-plenary-slot,
  .ph-plenary-slot {
    width: 100% !important;
    max-width: 100% !important;
    height: auto !important;
    min-height: 0 !important;
  }
  /* The decorative non-plenary sketches (vintage ticket on register
     etc) keep the 180×240 framing — only override for plenary. */
}


/* ============================================================
   PLENARY SLOT — kill aspect-ratio constraint on phone
   ============================================================ */
@media (max-width: 640px) {
  /* The .ph-plenary-slot has aspect-ratio: 720/460 which clamps
     its height to ~57% of width. At 331px wide that's 211px —
     too short for the trio of stacked plenary cards. Reset. */
  .ph-plenary-slot,
  .page-header-sketch.ph-plenary-slot {
    aspect-ratio: auto !important;
    height: auto !important;
    min-height: 0 !important;
  }
  /* The grid container inside also needs to grow with its content */
  .ph-plenary-slot .ph-plenary-grid {
    height: auto !important;
  }
}


/* ============================================================
   SPEAKERS — sort/filter strips + reader panel (phone)
   ============================================================ */
@media (max-width: 640px) {
  /* The filter chip strips (guild-filter, day-filter) and their
     pills were rendering as a single overflowing flex row. Convert
     to a horizontally-scrollable chip strip. */
  .guild-filter,
  .day-filter,
  .speakers-filter,
  .sp-filter,
  [class*="guild-filter"]:not([class*="-label"]):not([class*="-glyph"]),
  [class*="day-filter"] {
    display: flex !important;
    flex-wrap: nowrap !important;
    overflow-x: auto !important;
    overflow-y: visible !important;
    gap: 8px !important;
    padding: 8px 16px !important;
    margin: 0 -16px 8px !important;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .guild-filter::-webkit-scrollbar,
  .day-filter::-webkit-scrollbar { display: none; }
  .guild-pill,
  .day-pill,
  .track-pill,
  [class*="guild-pill"],
  [class*="day-pill"] {
    flex: 0 0 auto !important;
    width: auto !important;
    min-width: 0 !important;
    padding: 7px 14px !important;
    font-size: 10.5px !important;
    letter-spacing: 0.16em !important;
    white-space: nowrap !important;
    line-height: 1.4 !important;
  }
  /* The filter-label separators ("— By guild —", "— By day —") */
  .guild-filter-label,
  .day-filter-label,
  [class*="filter-label"] {
    flex: 0 0 100% !important;
    width: 100% !important;
    padding: 6px 0 2px !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10px !important;
    letter-spacing: 0.22em !important;
    text-transform: uppercase !important;
    color: var(--muted, #6B5A36) !important;
    text-align: center !important;
  }
  /* The "Sort —" / "by day" header pair — clean stack */
  .sp-sort-head,
  [class*="sort-head"] {
    display: flex !important;
    flex-direction: column !important;
    align-items: center !important;
    gap: 4px !important;
    padding: 8px 0 !important;
    text-align: center !important;
  }

  /* === Reader panel inner band === */
  .reader-panel-band {
    margin-left: 0 !important;
    margin-right: 0 !important;
    padding: 24px 16px !important;
  }
  .reader-panel {
    padding: 20px 16px !important;
  }
  .reader-panel-head {
    width: 100% !important;
    max-width: 100% !important;
  }
  .reader-panel-help {
    max-width: 100% !important;
    font-size: 14px !important;
    line-height: 1.5 !important;
  }
}


/* ============================================================
   SPEAKERS — filter-row / filter-row-pills (actual classes)
   ============================================================ */
@media (max-width: 640px) {
  /* The runtime-injected filter UI uses .filter-row + .filter-row-pills
     containers (NOT .guild-filter directly). Target those to scroll. */
  .filter-row,
  .guild-filter .filter-row {
    display: flex !important;
    flex-direction: column !important;
    gap: 6px !important;
    margin: 0 0 14px !important;
    padding: 0 !important;
  }
  .filter-row-label,
  .filter-row > .label,
  [class*="filter-row-label"] {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10px !important;
    letter-spacing: 0.22em !important;
    text-transform: uppercase !important;
    color: var(--muted, #6B5A36) !important;
    text-align: center !important;
    padding: 6px 0 4px !important;
  }
  .filter-row-pills,
  .guild-filter .filter-row-pills,
  .day-filter .filter-row-pills,
  [class*="filter-row-pills"] {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    overflow-x: auto !important;
    overflow-y: visible !important;
    gap: 8px !important;
    padding: 6px 16px 6px !important;
    margin: 0 -16px !important;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    width: auto !important;
  }
  .filter-row-pills::-webkit-scrollbar { display: none; }
  .filter-row-pills .guild-pill,
  .filter-row-pills .day-pill,
  .filter-row-pills > button,
  .filter-row-pills > a {
    flex: 0 0 auto !important;
    width: auto !important;
    min-width: 0 !important;
    padding: 8px 14px !important;
    font-size: 10.5px !important;
    letter-spacing: 0.14em !important;
    white-space: nowrap !important;
    line-height: 1.3 !important;
    display: inline-flex !important;
    align-items: center !important;
    gap: 6px !important;
    border-radius: 18px !important;
  }
  /* The count badge inside each pill ("15", "4", "8", "3") */
  .filter-row-pills .guild-pill .count,
  .filter-row-pills .guild-pill [class*="count"],
  .filter-row-pills .day-pill .count,
  .filter-row-pills .day-pill [class*="count"] {
    font-size: 10px !important;
    opacity: 0.7 !important;
    margin-left: 2px !important;
  }
}


/* ============================================================
   SPEAKERS — bottom illustrations larger on phone
   ============================================================ */
@media (max-width: 640px) {
  /* The vaulted-hall perspective SVG at the bottom of speakers.html
     was rendering at 331×211 — readable but small. Break out of the
     16px section padding so it spans edge-to-edge for visual weight. */
  .speakers-hall,
  svg.speakers-hall {
    width: 100vw !important;
    max-width: 100vw !important;
    margin-left: -16px !important;
    margin-right: -16px !important;
    height: auto !important;
    display: block !important;
  }
  /* The decorative .speakers-ornament + closing sk-svg footer ornament */
  .speakers-ornament,
  .speakers-ornament svg {
    width: 100% !important;
    height: auto !important;
    margin: 16px auto !important;
  }
  /* Closing sketch (e.g. lectern / quill icon at very bottom of
     speakers page) */
  section.speakers > .sk-svg,
  section.speakers svg.sk-svg:last-of-type {
    width: min(220px, 60vw) !important;
    height: auto !important;
    margin: 28px auto !important;
    display: block !important;
  }
}


/* ============================================================
   SPEAKERS — filter / search final fix (phone)
   The filter-row was wrapping with the BY GUILD label overlapping
   the BY DAY label and the SORT dropdown. Force clean vertical
   stack with proper margin between each row. Also fix the search
   input that was being clipped on the left edge.
   ============================================================ */
@media (max-width: 640px) {
  /* Container for the whole filter rail */
  .guild-filter,
  #guild-filter {
    display: block !important;
    width: 100% !important;
    max-width: 100% !important;
    overflow: hidden !important;
    margin: 0 !important;
    padding: 8px 0 !important;
  }
  /* Each filter row gets its own vertical block */
  .guild-filter > .filter-row,
  #guild-filter > .filter-row,
  .filter-row {
    display: block !important;
    width: 100% !important;
    max-width: 100% !important;
    margin: 0 0 18px !important;
    padding: 0 !important;
    grid-template-columns: none !important;
  }
  /* Reset any leftover flex/grid behavior on filter-row that was
     making it wrap labels onto pill rows. */
  .filter-row::before, .filter-row::after { content: none !important; display: none !important; }

  /* Labels on their own line */
  .filter-row-label,
  .filter-row > .label,
  [class*="filter-row-label"] {
    display: block !important;
    width: 100% !important;
    margin: 0 0 8px !important;
    padding: 0 !important;
    text-align: center !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10px !important;
    letter-spacing: 0.22em !important;
    text-transform: uppercase !important;
    color: var(--muted, #6B5A36) !important;
    line-height: 1.4 !important;
  }
  /* Pill strip — its own row, horizontally scrollable */
  .filter-row-pills,
  [class*="filter-row-pills"] {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    overflow-x: auto !important;
    overflow-y: visible !important;
    gap: 8px !important;
    padding: 4px 16px !important;
    margin: 0 -16px !important;
    width: auto !important;
    max-width: none !important;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .filter-row-pills::-webkit-scrollbar { display: none; }

  /* Pills — fixed compact size, no overlap */
  .filter-row-pills .guild-pill,
  .filter-row-pills .day-pill,
  .filter-row-pills > button,
  .filter-row-pills > a,
  .guild-pill,
  .day-pill {
    flex: 0 0 auto !important;
    width: auto !important;
    min-width: 0 !important;
    padding: 8px 14px !important;
    font-size: 10.5px !important;
    letter-spacing: 0.14em !important;
    line-height: 1.3 !important;
    white-space: nowrap !important;
    display: inline-flex !important;
    align-items: center !important;
    gap: 6px !important;
    border-radius: 18px !important;
    background: transparent !important;
  }
  /* Search input — was being cut off on the left ("eakers...")
     because of negative margin or container width. Force flow. */
  .speakers-search,
  .sp-search,
  input[type="search"],
  [class*="speakers-search"] {
    width: calc(100% - 8px) !important;
    max-width: 100% !important;
    box-sizing: border-box !important;
    margin: 0 4px 12px !important;
    padding: 12px 14px 12px 38px !important;
    font-size: 15px !important;
    background-position: 12px center !important;
  }
  /* The SORT/dropdown widget — center it on its own row */
  .sort-row,
  [class*="sort-row"],
  .speakers-sort {
    display: flex !important;
    flex-direction: row !important;
    align-items: center !important;
    justify-content: center !important;
    gap: 12px !important;
    margin: 12px 0 !important;
    flex-wrap: wrap;
  }
  .sort-row select,
  .speakers-sort select {
    padding: 10px 14px !important;
    font-size: 14px !important;
    min-height: 40px;
    border-radius: 4px !important;
  }
}


/* ============================================================
   TUTORIALS — bench-day CTA scribble cleanup (phone)
   ============================================================ */
@media (max-width: 640px) {
  /* The .reserve-cta-wrap contains the brass "Reserve a seat →"
     button + a decorative .reserve-note hand-drawn scribble that
     loops "— open the door" with an arrow pointing at the button.
     On desktop the scribble sits in the negative space beside the
     button as a tasteful flourish. On phone the SVG renders at
     full width with the scribble visually disconnected from the
     button — looks like broken text. Hide the scribble on mobile;
     the button alone is enough. */
  .reserve-note,
  .reserve-cta-wrap .reserve-note {
    display: none !important;
  }
  /* Tighten the wrap so the button is centered with proper padding */
  .reserve-cta-wrap {
    display: flex !important;
    flex-direction: column !important;
    align-items: center !important;
    gap: 0 !important;
    padding: 18px 16px !important;
  }
  .reserve-cta-wrap .btn,
  .reserve-cta-wrap .tut-cta-primary {
    width: 100% !important;
    justify-content: center !important;
    text-align: center !important;
  }
}


/* ============================================================
   TUTORIALS — page-header clock sketch + meta date row (phone)
   ============================================================ */
@media (max-width: 640px) {
  /* The clock illustration .page-header-sketch is a 331×331 SVG
     that sits in the page-header. With the page-header-meta
     ("Mon 12 Oct · 09:00 — 17:00") rendered after the H1, the
     clock SVG overlaps the date row because the page-header
     content area is not tall enough to clear the SVG. Force the
     sketch container to flow inline (cap height) so subsequent
     siblings sit below it cleanly. */
  .page-header-sketch:not(.ph-plenary-slot) {
    width: min(220px, 60vw) !important;
    height: auto !important;
    aspect-ratio: 1 / 1 !important;
    margin: 18px auto 24px !important;
    overflow: visible !important;
    display: block !important;
  }
  .page-header-sketch:not(.ph-plenary-slot) > svg.sk-svg,
  .page-header-sketch:not(.ph-plenary-slot) > svg {
    width: 100% !important;
    height: auto !important;
    max-width: 100% !important;
    display: block !important;
  }
  /* If the page-header-inner has the sketch + meta in a grid, force
     stack with the meta below the sketch. */
  .page-header-inner {
    display: block !important;
  }
  .page-header-inner > .page-header-sketch + *,
  .page-header-inner > * {
    margin-top: 0 !important;
  }
}


/* ============================================================
   TUTORIALS — confirmed tutorials as vertical editorial cards
   (phone) — override the swipe-gallery rule from earlier so
   each card reads as a full-width journal entry instead of a
   compare-shop swipe.
   ============================================================ */
@media (max-width: 640px) {
  /* Convert the .tut-grid from horizontal swipe back to vertical
     stack on phone. Editorial reading flow, not compare-shop. */
  .tut-grid {
    display: flex !important;
    flex-direction: column !important;
    gap: 0 !important;
    overflow-x: visible !important;
    overflow-y: visible !important;
    scroll-snap-type: none !important;
    padding: 0 !important;
    margin: 0 !important;
  }
  .tut-grid::-webkit-scrollbar { display: none; }
  .tut-grid::after {
    display: none !important;
    content: none !important;
  }
  .tut-grid > .tut-card,
  .tut-grid > * {
    flex: 1 1 100% !important;
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    scroll-snap-align: none !important;
  }

  /* Each tutorial card — editorial vertical layout */
  .tut-card {
    display: block !important;
    grid-template-columns: none !important;
    padding: 28px 4px 32px !important;
    margin: 0 !important;
    background: transparent !important;
    border: 0 !important;
    border-top: 1px solid var(--rule-2, rgba(40,28,12,0.18)) !important;
    border-radius: 0 !important;
    box-shadow: none !important;
  }
  .tut-card:first-of-type {
    border-top: 1px solid var(--rule-2, rgba(40,28,12,0.18)) !important;
    padding-top: 32px !important;
  }
  /* Last card gets a closing rule */
  .tut-card:last-of-type {
    border-bottom: 1px solid var(--rule-2, rgba(40,28,12,0.18));
    padding-bottom: 32px !important;
  }
  /* Bench number (spine) — large gilt Roman numeral as the
     "I." / "II." / "III." / "IV." anchor at top-left */
  .tut-card .spine,
  .tut-card .num,
  .tut-card > .num {
    display: block !important;
    position: static !important;
    margin: 0 0 12px !important;
    padding: 0 !important;
    font-family: 'Newsreader', Georgia, serif !important;
    font-style: italic !important;
    font-weight: 300 !important;
    font-size: 36px !important;
    line-height: 1 !important;
    color: var(--gilt, #B68A3E) !important;
    width: auto !important;
    border: 0 !important;
    background: transparent !important;
    aspect-ratio: auto !important;
  }
  /* The "Session" pre-label inside .num */
  .tut-card .spine .pre,
  .tut-card .num .pre {
    display: block !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-style: normal !important;
    font-size: 10px !important;
    letter-spacing: 0.22em !important;
    text-transform: uppercase !important;
    font-weight: 400 !important;
    color: var(--muted, #6B5A36) !important;
    margin-bottom: 4px !important;
  }
  /* Title (h3) */
  .tut-card h3,
  .tut-card .tut-card-h3,
  .tut-card .title {
    font-family: 'Newsreader', Georgia, serif !important;
    font-style: italic !important;
    font-weight: 400 !important;
    font-size: 24px !important;
    line-height: 1.2 !important;
    color: var(--ink, #1A1208) !important;
    margin: 0 0 10px !important;
    text-wrap: pretty;
  }
  /* Tutor name + affiliation — small caps row beneath title */
  .tut-card .tut-tutor,
  .tut-card [class*="tutor"]:not([class*="-call"]) {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10.5px !important;
    letter-spacing: 0.18em !important;
    text-transform: uppercase !important;
    color: var(--gilt, #B68A3E) !important;
    margin: 0 0 14px !important;
    line-height: 1.5 !important;
  }
  /* Abstract paragraph(s) */
  .tut-card p,
  .tut-card .lede,
  .tut-card .abstract {
    font-family: 'Newsreader', Georgia, serif !important;
    font-weight: 300 !important;
    font-size: 15.5px !important;
    line-height: 1.55 !important;
    color: var(--ink, #1A1208) !important;
    margin: 0 0 12px !important;
  }
  /* Italic emphasis inside abstract stays italic */
  .tut-card p em,
  .tut-card .lede em {
    font-style: italic !important;
    color: var(--filament-d, #8a6620) !important;
  }
  /* Meta row (when · duration · seats) */
  .tut-card .meta-row,
  .tut-card .tut-meta,
  .tut-card [class*="meta"]:not([class*="-cap"]):not([class*="-num"]) {
    display: flex !important;
    flex-wrap: wrap !important;
    gap: 6px 14px !important;
    margin: 8px 0 16px !important;
    padding: 0 !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10px !important;
    letter-spacing: 0.18em !important;
    text-transform: uppercase !important;
    color: var(--muted, #6B5A36) !important;
    border: 0 !important;
  }
  /* Reserve button — full width pill */
  .tut-card a.btn,
  .tut-card .btn-pill,
  .tut-card [class*="btn-reserve"],
  .tut-card a[href*="register"] {
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    gap: 6px !important;
    margin: 4px 0 0 !important;
    padding: 11px 18px !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10.5px !important;
    letter-spacing: 0.18em !important;
    text-transform: uppercase !important;
    border: 1px solid var(--rule-2, rgba(40,28,12,0.22)) !important;
    border-radius: 2px !important;
    background: transparent !important;
    color: var(--ink, #1A1208) !important;
    text-decoration: none !important;
    width: auto !important;
  }

  /* The "is-confirmed" gilt accent on confirmed cards */
  .tut-card.is-confirmed::before,
  .tut-card.is-confirmed::after {
    display: none !important;
  }
}


/* ============================================================
   TUTORIALS — confirmed card content overlap + top CTA row
   ============================================================ */
@media (max-width: 640px) {
  /* The .tut-card.is-confirmed has a decorative wax-seal stamp
     ("Confirmed / Sodalitas · MMXXVI" + "— § —") that was
     absolute-positioned on desktop alongside the schematic SVG.
     On phone after my vertical-stack override these now collapse
     into the same flow and crash into the duration-tag + badge.
     Hide the decorative seal — the explicit .badge.confirmed pill
     already conveys the same info. Hide the schematic too — it's
     decoration that doesn't translate at narrow widths. */
  .tut-card .t-line,
  .tut-card .t-main,
  .tut-card .seal,
  .tut-card .schematic,
  .tut-card [class*="t-line"],
  .tut-card [class*="t-main"]:not([class*="tutor"]),
  .tut-card [class*="schematic"] {
    display: none !important;
  }
  /* Header row inside card: Session label + Held in info — stack */
  .tut-card .spine {
    display: flex !important;
    flex-direction: column !important;
    align-items: flex-start !important;
    gap: 8px !important;
    margin-bottom: 16px !important;
    padding: 0 !important;
    grid-template-columns: none !important;
  }
  .tut-card .spine > * {
    grid-column: auto !important;
    grid-row: auto !important;
    margin: 0 !important;
  }
  /* The "Held in / In the round / Bench I" cluster */
  .tut-card .held-in,
  .tut-card .where,
  .tut-card .which {
    display: inline-flex !important;
    flex-wrap: wrap !important;
    gap: 4px 12px !important;
    align-items: baseline !important;
  }
  /* The Confirmed badge + Full day duration — sit on one row */
  .tut-card .badge,
  .tut-card .duration-tag {
    display: inline-flex !important;
    align-items: center !important;
    padding: 7px 12px !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 11px !important;
    letter-spacing: 0.18em !important;
    text-transform: uppercase !important;
    border: 1px solid var(--rule-2, rgba(40,28,12,0.22)) !important;
    border-radius: 2px !important;
    margin: 0 8px 8px 0 !important;
    background: transparent !important;
    line-height: 1 !important;
    font-weight: 500 !important;
  }
  .tut-card .badge.confirmed {
    color: var(--accent, #4A6B5C) !important;
    border-color: rgba(74, 107, 92, 0.4) !important;
  }
  /* The "led-by-mark" tutor label + name */
  .tut-card .led-by-mark {
    display: block !important;
    margin: 12px 0 4px !important;
  }
  .tut-card .by-name {
    display: block !important;
    font-family: 'Newsreader', Georgia, serif !important;
    font-style: italic !important;
    font-size: 18px !important;
    line-height: 1.3 !important;
    color: var(--ink, #1A1208) !important;
  }
  /* Meta strip inside card ("~30 seats · BYO laptop ·
     beginner — intermediate") + a "Reserve a seat" inline link
     that's overlapping. Force the link onto its own row. */
  .tut-card .tut-meta-strip,
  .tut-card [class*="meta-strip"],
  .tut-card .seat-meta {
    display: flex !important;
    flex-direction: column !important;
    align-items: flex-start !important;
    gap: 10px !important;
    margin: 10px 0 16px !important;
    padding: 0 !important;
  }
  .tut-card .tut-meta-strip > *,
  .tut-card .seat-meta > * {
    width: 100% !important;
    margin: 0 !important;
  }
  /* Reserve link inside card should be a clear secondary action */
  .tut-card .tut-meta-strip a,
  .tut-card .seat-meta a,
  .tut-card a[href*="register"] {
    margin-top: 4px !important;
    align-self: stretch !important;
  }

  /* ============================================================
     TOP CTA ROW — pin "Reserve a seat" + "Propose a tutorial" +
     countdown stamp at the top of the tutorials page on phone.
     Uses sticky positioning under the topnav so users always see
     both primary actions. Hides the decorative scribble pieces. */
  body.tutorials-page .tut-top-cta,
  body[class*="tutorials"] .tut-top-cta {
    display: flex !important;
    position: sticky !important;
    top: 56px !important;
    z-index: 60 !important;
    background: rgba(244, 236, 218, 0.96) !important;
    backdrop-filter: blur(8px) !important;
    -webkit-backdrop-filter: blur(8px) !important;
    padding: 10px 14px !important;
    margin: 0 -16px 16px !important;
    border-top: 1px solid rgba(40, 28, 12, 0.10) !important;
    border-bottom: 1px solid rgba(40, 28, 12, 0.10) !important;
    gap: 10px !important;
    align-items: center !important;
    justify-content: space-between !important;
    flex-wrap: nowrap !important;
  }
  .tut-top-cta .btn {
    padding: 10px 14px !important;
    font-size: 10.5px !important;
    letter-spacing: 0.14em !important;
    min-height: 44px !important;
    flex: 1 1 auto !important;
    text-align: center !important;
    justify-content: center !important;
  }
}


/* ============================================================
   TUTORIALS — page-header CTA buttons side-by-side (phone)
   "Reserve a seat" + "Propose a tutorial" sit in a vertical
   stack by default. User wants them in a clean two-up row.
   ============================================================ */
@media (max-width: 640px) {
  .page-header .hero-cta-row,
  .page-header .ph-cta-row,
  .page-header [class*="cta-row"],
  .page-header .hero-actions,
  .page-header [class*="actions"] {
    display: flex !important;
    flex-direction: row !important;
    gap: 10px !important;
    align-items: stretch !important;
    justify-content: stretch !important;
    flex-wrap: nowrap !important;
    margin-bottom: 16px !important;
  }
  .page-header .hero-cta-row > .btn,
  .page-header .ph-cta-row > .btn,
  .page-header [class*="cta-row"] > .btn,
  .page-header .hero-actions > .btn,
  .page-header [class*="actions"] > .btn,
  .page-header .hero-cta-row > a,
  .page-header [class*="cta-row"] > a {
    flex: 1 1 50% !important;
    min-width: 0 !important;
    padding: 12px 8px !important;
    font-size: 9.5px !important;
    letter-spacing: 0.12em !important;
    text-align: center !important;
    justify-content: center !important;
    word-break: keep-all !important;
    white-space: normal !important;
    line-height: 1.3 !important;
    min-height: 48px !important;
  }
  /* Hide arrow inline glyph on phone if it forces a second line */
  .page-header .hero-cta-row .btn .arr,
  .page-header [class*="cta-row"] .btn .arr {
    font-size: 11px !important;
    margin-left: 2px !important;
  }
}


/* ============================================================
   TUTORIALS — confirmed stamp display fix (phone)
   The .tut-confirmed-stamp container shows three pieces:
   t-line.t-top, t-main, t-line.t-bot. My earlier rule hid them
   individually but the empty container's decorative border
   (corner brackets ::before/::after) still rendered as a visible
   empty box next to the .badge.confirmed pill. Replace: show the
   full stamp cleanly (it's the only confirmation indicator) and
   hide the duplicate .badge.confirmed pill. */
@media (max-width: 640px) {
  /* Restore visibility on stamp lines */
  .tut-card .tut-confirmed-stamp .t-line,
  .tut-card .tut-confirmed-stamp .t-main,
  .tut-card .t-line,
  .tut-card .t-main {
    display: block !important;
    text-align: center !important;
  }
  .tut-card .tut-confirmed-stamp {
    display: inline-block !important;
    margin: 8px 0 12px !important;
    padding: 10px 18px !important;
    text-align: center !important;
    border: 1px solid rgba(74, 107, 92, 0.35) !important;
    border-radius: 2px !important;
    background: rgba(74, 107, 92, 0.04) !important;
  }
  .tut-card .tut-confirmed-stamp .t-main {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 11px !important;
    letter-spacing: 0.22em !important;
    text-transform: uppercase !important;
    color: var(--accent, #4A6B5C) !important;
    font-weight: 600 !important;
    line-height: 1.2 !important;
    margin: 2px 0 !important;
  }
  .tut-card .tut-confirmed-stamp .t-line {
    font-family: 'Newsreader', Georgia, serif !important;
    font-style: italic !important;
    font-size: 9px !important;
    letter-spacing: 0.18em !important;
    color: rgba(74, 107, 92, 0.6) !important;
    margin: 0 !important;
    line-height: 1.2 !important;
  }
  /* Remove the .tut-confirmed-stamp's own border-brackets if any */
  .tut-card .tut-confirmed-stamp::before,
  .tut-card .tut-confirmed-stamp::after {
    display: none !important;
    content: none !important;
  }
  /* Hide the duplicate .badge.confirmed pill so we only show one
     confirmation indicator. */
  .tut-card .badge.confirmed {
    display: none !important;
  }
}


/* ============================================================
   TUTORIALS — final fix: buttons side-by-side + bigger stamp
   ============================================================ */
@media (max-width: 640px) {
  /* The .tut-hero-cta-pair is already flex with two children:
     .reserve-cta-wrap (button 1) + .btn.tut-cta-secondary (button 2).
     Force flex-row so they sit side-by-side, each ~50% wide. */
  .tut-hero-cta-pair {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    gap: 10px !important;
    align-items: stretch !important;
    width: 100% !important;
    padding: 0 !important;
  }
  .tut-hero-cta-pair > .reserve-cta-wrap,
  .tut-hero-cta-pair > .btn,
  .tut-hero-cta-pair > a {
    flex: 1 1 calc(50% - 5px) !important;
    width: calc(50% - 5px) !important;
    min-width: 0 !important;
    max-width: calc(50% - 5px) !important;
    margin: 0 !important;
    padding: 0 !important;
  }
  /* The button INSIDE .reserve-cta-wrap fills its wrapper */
  .tut-hero-cta-pair > .reserve-cta-wrap > .btn {
    width: 100% !important;
    min-width: 0 !important;
  }
  /* Both buttons: tight padding so the small caps text fits */
  .tut-hero-cta-pair .btn {
    padding: 14px 8px !important;
    font-size: 9.5px !important;
    letter-spacing: 0.11em !important;
    text-align: center !important;
    justify-content: center !important;
    min-height: 50px !important;
    white-space: normal !important;
    line-height: 1.25 !important;
  }
  .tut-hero-cta-pair .btn .arr {
    margin-left: 3px !important;
  }

  /* === CONFIRMED STAMP — bigger, brighter, properly sized === */
  .tut-card .tut-confirmed-stamp {
    display: inline-block !important;
    margin: 14px 0 18px !important;
    padding: 14px 22px !important;
    text-align: center !important;
    border: 1.5px solid rgba(74, 107, 92, 0.45) !important;
    border-radius: 3px !important;
    background: rgba(74, 107, 92, 0.06) !important;
  }
  .tut-card .tut-confirmed-stamp .t-main {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 14px !important;
    letter-spacing: 0.26em !important;
    text-transform: uppercase !important;
    color: var(--accent, #4A6B5C) !important;
    font-weight: 600 !important;
    line-height: 1.2 !important;
    margin: 4px 0 !important;
    display: block !important;
  }
  .tut-card .tut-confirmed-stamp .t-line {
    display: block !important;
    font-family: 'Newsreader', Georgia, serif !important;
    font-style: italic !important;
    font-size: 11px !important;
    letter-spacing: 0.16em !important;
    color: rgba(74, 107, 92, 0.7) !important;
    margin: 0 !important;
    line-height: 1.3 !important;
  }
}


/* ============================================================
   TUTORIALS — .time-tba meta + Reserve button overlap (phone)
   The "~30 seats · BYO laptop · beginner — intermediate" .time-tba
   strip was overlapping with the inline "Reserve a seat" button
   in the same row. Force the parent to stack vertically on phone.
   ============================================================ */
@media (max-width: 640px) {
  /* The parent of .time-tba had a flex/grid layout that put a
     button beside it. Stack vertically and let the button sit
     on its own row underneath. */
  .tut-card .time-tba,
  .tut-card .time-row,
  .tut-card [class*="time-row"],
  .tut-card .time-tba ~ a,
  .tut-card .time-tba ~ .btn {
    width: 100% !important;
    max-width: 100% !important;
  }
  /* Force any row containing .time-tba to stack */
  .tut-card .time-row,
  .tut-card *:has(> .time-tba) {
    display: flex !important;
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 12px !important;
    margin: 12px 0 !important;
  }
  .tut-card .time-tba {
    display: block !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 10.5px !important;
    letter-spacing: 0.14em !important;
    text-transform: uppercase !important;
    color: var(--muted, #6B5A36) !important;
    line-height: 1.5 !important;
    padding: 0 !important;
    margin: 0 !important;
    text-align: left !important;
    background: transparent !important;
    border: 0 !important;
  }
  /* Reserve a seat button that follows the .time-tba — full width */
  .tut-card .time-tba + a,
  .tut-card .time-tba + .btn,
  .tut-card .time-tba ~ .btn-pill {
    display: block !important;
    width: 100% !important;
    margin: 4px 0 0 !important;
    text-align: center !important;
    padding: 12px 16px !important;
  }
}


/* ============================================================
   TUTORIALS — .foot-info parent collapse fix (phone)
   The .foot-info container was rendering at width:0, collapsing
   the .time-tba meta strip and Reserve button into a 1px column
   that visually overlapped. Force the foot-info AND its parent
   to display:block with full width on phone.
   ============================================================ */
@media (max-width: 640px) {
  .tut-card .foot,
  .tut-card .foot-info,
  .tut-card [class*="foot-info"],
  .tut-card *:has(> .foot-info),
  .tut-card *:has(> .time-tba) {
    display: block !important;
    flex-direction: column !important;
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    grid-template-columns: 1fr !important;
    grid-template-areas: none !important;
    overflow: visible !important;
  }
  /* Cancel any grid-area on children */
  .tut-card .foot > *,
  .tut-card .foot-info > * {
    grid-area: auto !important;
    grid-column: auto !important;
    grid-row: auto !important;
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    margin-bottom: 8px !important;
  }
  /* Force the .time-tba to render full width with no overflow */
  .tut-card .time-tba {
    display: block !important;
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    white-space: normal !important;
    word-break: keep-all !important;
    overflow-wrap: normal !important;
    text-overflow: clip !important;
    overflow: visible !important;
    position: static !important;
    margin: 8px 0 12px !important;
    padding: 0 !important;
    font-size: 10.5px !important;
    line-height: 1.5 !important;
    letter-spacing: 0.14em !important;
    text-transform: uppercase !important;
    font-family: 'JetBrains Mono', monospace !important;
    color: var(--muted, #6B5A36) !important;
    background: transparent !important;
    border: 0 !important;
  }
  /* Any button that follows .time-tba renders on its own row */
  .tut-card .time-tba + *,
  .tut-card .time-tba ~ a.btn,
  .tut-card .time-tba ~ .btn,
  .tut-card .foot .btn,
  .tut-card .foot-info .btn {
    display: block !important;
    width: 100% !important;
    margin: 8px 0 0 !important;
    padding: 13px 16px !important;
    text-align: center !important;
    justify-content: center !important;
    position: static !important;
  }
}


/* ============================================================
   PROPOSE-TUTORIAL — 8 mobile improvements
   ============================================================ */
@media (max-width: 640px) {

  /* === 04 · "Four kinds of tutor" → swipe gallery === */
  .pt-who-grid {
    display: flex !important;
    flex-direction: row !important;
    grid-template-columns: none !important;
    overflow-x: auto !important;
    overflow-y: visible !important;
    scroll-snap-type: x mandatory;
    padding: 4px 16px 24px !important;
    margin: 0 -16px !important;
    gap: 14px !important;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .pt-who-grid::-webkit-scrollbar { display: none; }
  .pt-who-grid > * {
    flex: 0 0 82% !important;
    min-width: 0 !important;
    max-width: 82% !important;
    scroll-snap-align: start;
  }
  .pt-who-grid::after {
    content: 'swipe →';
    flex: 0 0 auto !important;
    align-self: center !important;
    padding: 6px 12px !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 9.5px !important;
    letter-spacing: 0.22em !important;
    text-transform: uppercase !important;
    background: rgba(40,28,12,0.85) !important;
    color: #F4ECDA !important;
    border-radius: 14px !important;
    height: 28px;
    display: inline-flex !important;
    align-items: center !important;
    pointer-events: none !important;
  }

  /* === 05 · Window timeline → vertical stepper ===
     Already stacks to 1fr at 540px breakpoint; tighten further on
     phone with a connecting gilt rule. */
  .pt-timeline {
    border-top: 0 !important;
    padding: 12px 0 !important;
  }
  .pt-timeline-step {
    display: grid !important;
    grid-template-columns: 60px 1fr !important;
    grid-template-rows: auto auto !important;
    gap: 4px 14px !important;
    padding: 14px 0 !important;
    position: relative;
  }
  .pt-timeline-step::before {
    content: '';
    position: absolute;
    left: 28px;
    top: 36px;
    bottom: -14px;
    width: 1px;
    background: rgba(182, 138, 62, 0.3);
  }
  .pt-timeline-step:last-child::before { display: none; }
  .pt-timeline-date {
    grid-row: 1 / 3 !important;
    grid-column: 1 !important;
    align-self: start !important;
  }
  .pt-timeline-date .month {
    font-size: 14px !important;
    letter-spacing: 0.12em !important;
  }
  .pt-timeline-date .year {
    font-size: 9.5px !important;
    margin-top: 2px !important;
  }
  .pt-timeline-body {
    grid-row: 1 / 3 !important;
    grid-column: 2 !important;
    margin: 0 !important;
  }
  .pt-timeline-body h3 {
    font-size: 17px !important;
    line-height: 1.25 !important;
    margin: 0 0 6px !important;
  }
  .pt-timeline-body p {
    font-size: 14px !important;
    line-height: 1.5 !important;
  }

  /* === 06 · "What we provide" → full-width vertical cards ===
     2-col was too cramped — text wrapped mid-word. Switch to
     1-col with full reading width, each card a proper editorial
     plate. */
  .pt-provide-grid {
    display: grid !important;
    grid-template-columns: 1fr !important;
    gap: 14px !important;
    padding: 0 !important;
  }
  .pt-provide-item {
    margin: 0 !important;
  }
  .pt-provide-frame {
    padding: 22px 20px 18px !important;
    margin: 6px !important;
  }
  .pt-provide-num {
    font-size: 28px !important;
  }
  .pt-provide-tag {
    font-size: 9.5px !important;
    letter-spacing: 0.20em !important;
  }
  .pt-provide-glyph {
    width: 52px !important;
    height: 52px !important;
    margin: 10px 0 !important;
  }
  .pt-provide-item h3 {
    font-size: 19px !important;
    line-height: 1.2 !important;
    margin: 8px 0 !important;
  }
  .pt-provide-item p {
    font-size: 14.5px !important;
    line-height: 1.55 !important;
  }

  /* === 03 · FAQ accordion — pt-faq-item gets the same treatment ===
     Mobile-enhancements.js already wires .faq-item — extend to
     .pt-faq-item via the same CSS rules. */
  .pt-faq-item {
    border-bottom: 1px solid var(--rule-2, rgba(40,28,12,0.14));
    padding: 0 !important;
    margin: 0;
  }
  .pt-faq-item h3,
  .pt-faq-item h4 {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 16px 0;
    margin: 0;
    cursor: pointer;
    font-size: 16px;
    line-height: 1.35;
    user-select: none;
  }
  .pt-faq-item h3::after,
  .pt-faq-item h4::after {
    content: '+';
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--rule-2, rgba(40,28,12,0.22));
    border-radius: 50%;
    font-family: 'JetBrains Mono', monospace;
    font-size: 16px;
    color: var(--gilt, #B68A3E);
  }
  .pt-faq-item.is-open h3::after,
  .pt-faq-item.is-open h4::after {
    content: '−';
    background: var(--ink);
    color: var(--paper);
    border-color: var(--ink);
  }
  .pt-faq-item > p,
  .pt-faq-item > div {
    max-height: 0;
    overflow: hidden;
    opacity: 0;
    margin: 0 !important;
    padding: 0 !important;
    transition: max-height 320ms ease, opacity 220ms ease, padding 220ms ease;
  }
  .pt-faq-item.is-open > p,
  .pt-faq-item.is-open > div {
    max-height: 800px;
    opacity: 1;
    padding: 0 0 18px !important;
  }
  .pt-faq-list {
    grid-template-columns: 1fr !important;
    gap: 0 !important;
  }

  /* === 01 · STICKY BOTTOM CTA (propose-tutorial-page) === */
  body.propose-tutorial-page .pt-mobile-stickybar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 88;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
    background: rgba(244, 236, 218, 0.96);
    border-top: 1px solid var(--rule-2, rgba(40,28,12,0.22));
    box-shadow: 0 -8px 18px -8px rgba(40,28,12,0.18);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    transform: translateY(120%);
    transition: transform 320ms cubic-bezier(.22,.61,.36,1);
  }
  body.propose-tutorial-page.show-stickybar .pt-mobile-stickybar {
    transform: translateY(0);
  }
  body.propose-tutorial-page.show-stickybar {
    padding-bottom: 80px;
  }
  .pt-mobile-stickybar .info {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    flex: 1 1 auto;
  }
  .pt-mobile-stickybar .eyebrow {
    font-family: 'JetBrains Mono', monospace;
    font-size: 9.5px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--gilt, #B68A3E);
  }
  .pt-mobile-stickybar .deadline {
    font-family: 'Newsreader', Georgia, serif;
    font-style: italic;
    font-size: 14px;
    color: var(--ink, #1A1208);
  }
  .pt-mobile-stickybar .cta {
    flex: 0 0 auto;
    background: linear-gradient(135deg, #C99A47 0%, #B68A3E 50%, #8a6620 100%);
    color: #FBF5E5;
    text-decoration: none;
    padding: 12px 16px;
    border-radius: 3px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 10.5px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    font-weight: 600;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    box-shadow: 0 2px 0 #6f5117, 0 6px 14px -3px rgba(40,28,12,0.35);
  }

  /* === 02 · SECTION TAB STRIP === */
  body.propose-tutorial-page .pt-mobile-tabstrip {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    overflow-y: visible;
    padding: 12px 16px;
    margin: 0 -16px 4px;
    border-top: 1px solid rgba(40,28,12,0.08);
    border-bottom: 1px solid rgba(40,28,12,0.08);
    background: rgba(244, 236, 218, 0.55);
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    position: sticky;
    top: 56px;
    z-index: 70;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
  }
  body.propose-tutorial-page .pt-mobile-tabstrip::-webkit-scrollbar { display: none; }
  .pt-mobile-tab {
    flex: 0 0 auto;
    padding: 7px 14px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 10.5px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--muted, #6B5A36);
    background: transparent;
    border: 1px solid var(--rule-2, rgba(40,28,12,0.18));
    border-radius: 20px;
    text-decoration: none;
    white-space: nowrap;
  }
  .pt-mobile-tab:active {
    background: var(--ink, #1A1208);
    color: var(--paper, #FBF5E5);
    border-color: var(--ink, #1A1208);
  }

  /* === 07 · QUICK-PICK header summary === */
  .pt-mobile-quickpick {
    display: flex !important;
    align-items: center !important;
    justify-content: space-around !important;
    gap: 8px !important;
    padding: 12px 16px !important;
    background: rgba(244, 236, 218, 0.55) !important;
    border: 1px solid rgba(40, 28, 12, 0.10) !important;
    border-radius: 4px !important;
    margin: 0 0 18px !important;
    flex-wrap: wrap;
  }
  .pt-mobile-quickpick > * {
    flex: 1 1 auto;
    text-align: center;
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ink, #1A1208);
    line-height: 1.4;
  }
  .pt-mobile-quickpick strong {
    display: block;
    font-family: 'Newsreader', Georgia, serif;
    font-style: italic;
    font-weight: 400;
    font-size: 16px;
    letter-spacing: -0.005em;
    text-transform: none;
    color: var(--gilt, #B68A3E);
    margin-bottom: 2px;
  }

  /* === 08 · Hero CTA pair side-by-side === */
  .page-header .pt-cta-pair,
  .page-header [class*="cta-pair"],
  .page-header .hero-actions {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    gap: 10px !important;
    margin-top: 18px !important;
  }
  .page-header .pt-cta-pair > .btn,
  .page-header [class*="cta-pair"] > .btn,
  .page-header [class*="cta-pair"] > a {
    flex: 1 1 50% !important;
    min-width: 0 !important;
    padding: 13px 8px !important;
    font-size: 9.5px !important;
    letter-spacing: 0.11em !important;
    text-align: center !important;
    justify-content: center !important;
    min-height: 48px !important;
    white-space: normal !important;
    line-height: 1.25 !important;
  }
}


/* ============================================================
   DINNERS — stamp-row "Three tables · one night · Mon 12 Oct"
   on one line (phone)
   ============================================================ */
@media (max-width: 640px) {
  /* The dinners-page stamp-row text "Three tables · one night ·
     Mon 12 October" was wrapping to 2 lines. Shrink the font and
     letter-spacing so it fits on one line at 343px wide. */
  body[class*="dinners"] .stamp-row,
  section#dinners .stamp-row,
  .dinners .stamp-row {
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    gap: 0 !important;
    text-align: center !important;
    overflow: visible !important;
  }
  body[class*="dinners"] .stamp-row > span,
  section#dinners .stamp-row > span,
  .dinners .stamp-row > span {
    font-size: 9.5px !important;
    letter-spacing: 0.16em !important;
    white-space: nowrap !important;
    line-height: 1.4 !important;
    display: inline-block !important;
    width: auto !important;
  }
}


/* ============================================================
   VENUE — "First time in Prague" .glints grid layout (phone)
   ============================================================ */
@media (max-width: 640px) {
  /* The .v-stamps grid stays as 1-col rows (currency/language list).
     The .glints city-iconography strip switches to a compact 2-up
     mini-grid on phone — each card sits as a centered icon + italic
     name + small-caps meta tile. Cuts vertical length in half. The
     5th orphan card spans both columns to centre cleanly. */
  .v-stamps {
    display: grid !important;
    grid-template-columns: 1fr !important;
    gap: 0 !important;
    margin: 16px -16px !important;
    padding: 0 !important;
    border-top: 1px solid var(--rule-2, rgba(40,28,12,0.18)) !important;
    border-bottom: 1px solid var(--rule-2, rgba(40,28,12,0.18)) !important;
    background: rgba(244, 236, 218, 0.30) !important;
  }
  .glints,
  [class*="glints"] {
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
    gap: 10px !important;
    margin: 16px 0 !important;
    padding: 0 !important;
    background: transparent !important;
    border: 0 !important;
  }
  .v-stamp,
  .v-stamps > * {
    display: grid !important;
    grid-template-columns: 100px 1fr !important;
    align-items: baseline !important;
    column-gap: 16px !important;
    padding: 14px 18px !important;
    border-right: 0 !important;
    border-bottom: 1px solid rgba(40, 28, 12, 0.10) !important;
    text-align: left !important;
    min-height: 0 !important;
    width: 100% !important;
    max-width: 100% !important;
  }
  /* Glints — compact centered icon tiles */
  .glint,
  .glints > * {
    display: flex !important;
    flex-direction: column !important;
    align-items: center !important;
    justify-content: flex-start !important;
    gap: 8px !important;
    padding: 16px 10px !important;
    border: 1px solid rgba(182,138,62,0.32) !important;
    background: rgba(244, 236, 218, 0.35) !important;
    text-align: center !important;
    text-decoration: none !important;
    min-height: 0 !important;
    width: 100% !important;
    max-width: 100% !important;
    box-sizing: border-box;
  }
  /* 5th glint — span both columns, centered */
  .glints > *:nth-child(5):last-child {
    grid-column: 1 / -1 !important;
    max-width: 70% !important;
    justify-self: center !important;
    margin: 0 auto !important;
  }
  /* Icon in each glint */
  .glint > svg,
  .glints > * > svg {
    width: auto !important;
    height: 32px !important;
    max-width: 60px !important;
    display: block !important;
    flex: 0 0 auto;
  }
  /* Last row — no bottom border (only applies to v-stamps now) */
  .v-stamp:last-child,
  .v-stamps > *:last-child {
    border-bottom: 0 !important;
  }
  /* Each label (§ Currency etc) — v-stamps only */
  .v-stamp .k,
  .v-stamp [class*="-k"],
  .v-stamps > * > *:first-child {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 9px !important;
    letter-spacing: 0.18em !important;
    text-transform: uppercase !important;
    color: var(--gilt, #B68A3E) !important;
    display: block !important;
    margin-bottom: 6px !important;
    line-height: 1.3 !important;
  }
  /* The big value — v-stamps and glints both */
  .v-stamp .v,
  .v-stamp [class*="-v"],
  .v-stamps > * > *:nth-child(2),
  .glint .name,
  .glints > * .name {
    font-family: 'Newsreader', Georgia, serif !important;
    font-style: italic !important;
    font-size: 15px !important;
    line-height: 1.2 !important;
    color: var(--ink, #1A1208) !important;
    margin: 0 !important;
  }
  /* Meta under the name */
  .glint .meta,
  .glints > * .meta {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 9px !important;
    letter-spacing: 0.14em !important;
    text-transform: uppercase !important;
    color: var(--muted, #6B5A36) !important;
    line-height: 1.3 !important;
    margin: 0 !important;
  }
}


/* ============================================================
   VENUE — section padding + inter-block spacing (phone)
   ============================================================ */
@media (max-width: 640px) {
  /* The section .venue has 40px 16px padding on phone. Inner
     .v-block elements each have either 96px or 56px margin-top
     (too much vertical gap) and some have -24px lateral margin
     (mismatched with section's 16px padding, creating 8px
     overhang each side). Normalize. */
  
  /* Tighten section vertical padding */
  section.venue,
  section.venue--book-section {
    padding: 32px 16px !important;
  }
  
  /* All v-blocks — sane inter-block margins */
  .v-block,
  div.v-block {
    margin: 32px 0 0 !important;
  }
  .v-block:first-of-type {
    margin-top: 0 !important;
  }
  
  /* Full-bleed blocks (.v-block--warm, .v-block--quiet) — match
     section's 16px padding exactly so they extend edge-to-edge
     cleanly without the 8px overhang. */
  .v-block--warm,
  .v-block--quiet {
    margin-left: -16px !important;
    margin-right: -16px !important;
    padding: 32px 16px !important;
    width: auto !important;
  }
  
  /* Plain blocks (no warm/quiet variant) keep zero horizontal
     margins so they sit inside the section's 16px padding. */
  .v-block:not(.v-block--warm):not(.v-block--quiet) {
    margin-left: 0 !important;
    margin-right: 0 !important;
  }
  
  /* Tighten the v-block-head spacing inside */
  .v-block-head,
  .v-block-inner {
    margin-bottom: 16px !important;
    padding: 0 !important;
  }
  
  /* The .v-block-lede (intro paragraph) reads tight */
  .v-block-lede {
    font-size: 15px !important;
    line-height: 1.5 !important;
    margin: 0 0 18px !important;
  }
}


/* ============================================================
   SPONSORS PAGE — 7 mobile improvements
   ============================================================ */
@media (max-width: 640px) {

  /* === 01 · FIX broken sponsor-tier logos grid ===
     The .sponsor-tier .logos had grid-template-columns: 625px
     (fixed track wider than viewport). Force 2-col actual fix. */
  section .sponsor-tier .logos,
  .sponsor-tier .logos {
    display: grid !important;
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    gap: 14px !important;
    width: 100% !important;
    max-width: 100% !important;
    overflow: visible !important;
    flex-direction: initial !important;
  }
  .sponsor-tier .logos > .logo,
  .sponsor-tier .logos > a {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    padding: 12px 8px !important;
  }
  .sponsor-tier .logos img {
    max-width: 100% !important;
    max-height: 70px !important;
    width: auto !important;
    height: auto !important;
    object-fit: contain !important;
  }
  /* Platinum solo logo gets full width */
  .sponsor-tier.platinum .logos,
  .sponsor-tier[data-tier="platinum"] .logos {
    grid-template-columns: 1fr !important;
  }
  .sponsor-tier.platinum .logos img {
    max-height: 110px !important;
  }
  
  /* The .n span (sponsor name?) was 365 wide overflowing — wrap */
  .sponsor-tier .n,
  .sponsor-tier [class*=" n"]:not([class*="name"]) {
    white-space: normal !important;
    max-width: 100% !important;
    font-size: 13px !important;
  }

  /* === 04 · TIER LEDGER → swipe gallery ===
     The 4 tier cards (Diamond/Gold/Silver/Bronze) stacked
     vertically at 6386px. Convert to swipe gallery. */
  .tier-ledger,
  [class*="tier-ledger-grid"],
  .tier-cards,
  [class*="tier-cards"] {
    display: flex !important;
    flex-direction: row !important;
    grid-template-columns: none !important;
    overflow-x: auto !important;
    overflow-y: visible !important;
    scroll-snap-type: x mandatory;
    padding: 4px 16px 24px !important;
    margin: 0 -16px !important;
    gap: 14px !important;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .tier-ledger::-webkit-scrollbar,
  .tier-cards::-webkit-scrollbar { display: none; }
  .tier-ledger > *,
  .tier-cards > * {
    flex: 0 0 85% !important;
    max-width: 85% !important;
    min-width: 0 !important;
    scroll-snap-align: start;
  }

  /* === 05 · NAMED PATRONAGES → 2-up tiles === */
  .sp-named .named-grid,
  .sp-named [class*="named-grid"],
  .sp-named [class*="grid"] {
    grid-template-columns: repeat(2, 1fr) !important;
    gap: 14px !important;
  }
  .sp-named .patron-card,
  .sp-named [class*="patron"] {
    padding: 14px !important;
  }
  .sp-named img {
    max-width: 100% !important;
    height: auto !important;
  }

  /* === 06 · USE OF FUNDS → cleaner row layout === */
  .patron-funds .funds-grid,
  .patron-funds [class*="funds"] {
    grid-template-columns: 1fr !important;
    gap: 12px !important;
  }
  .patron-funds .fund-row,
  .patron-funds [class*="fund-row"] {
    display: grid !important;
    grid-template-columns: 50px 1fr auto !important;
    gap: 14px !important;
    align-items: baseline !important;
    padding: 12px 0 !important;
    border-bottom: 1px solid var(--rule-2, rgba(40,28,12,0.14)) !important;
  }

  /* === 07 · AUDIENCE section compress === */
  section#audience,
  section.audience {
    padding-top: 32px !important;
    padding-bottom: 32px !important;
  }
  section#audience h2,
  section.audience h2 {
    margin-bottom: 16px !important;
  }
  section#audience .audience-stats,
  section.audience [class*="stats"] {
    grid-template-columns: repeat(2, 1fr) !important;
    gap: 12px !important;
  }

  /* === 02 · SECTION TAB STRIP (sponsors-page) === */
  body.sponsors-page .sp-mobile-tabstrip {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    overflow-y: visible;
    padding: 12px 16px;
    margin: 0 -16px 4px;
    border-top: 1px solid rgba(40,28,12,0.08);
    border-bottom: 1px solid rgba(40,28,12,0.08);
    background: rgba(244, 236, 218, 0.55);
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    position: sticky;
    top: 56px;
    z-index: 70;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
  }
  body.sponsors-page .sp-mobile-tabstrip::-webkit-scrollbar { display: none; }
  body.sponsors-page .sp-mobile-tab {
    flex: 0 0 auto;
    padding: 7px 14px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 10.5px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--muted, #6B5A36);
    background: transparent;
    border: 1px solid var(--rule-2, rgba(40,28,12,0.18));
    border-radius: 20px;
    text-decoration: none;
    white-space: nowrap;
  }
  /* On narrow phones (Galaxy S10 at 360, iPhone SE at 375),
     tighten the pill padding + gap so all five tabs fit on a
     single line without the last one ("Funds") clipping. */
  @media (max-width: 380px) {
    body.sponsors-page .sp-mobile-tabstrip {
      gap: 4px;
      padding: 10px 8px;
    }
    body.sponsors-page .sp-mobile-tab {
      padding: 6px 8px;
      font-size: 9.5px;
      letter-spacing: 0.10em;
    }
  }

  /* === 03 · STICKY "Become a sponsor" CTA === */
  body.sponsors-page .sp-mobile-stickybar {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 88;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
    background: rgba(244, 236, 218, 0.96);
    border-top: 1px solid var(--rule-2, rgba(40,28,12,0.22));
    box-shadow: 0 -8px 18px -8px rgba(40,28,12,0.18);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    transform: translateY(120%);
    transition: transform 320ms cubic-bezier(.22,.61,.36,1);
  }
  body.sponsors-page.show-stickybar .sp-mobile-stickybar {
    transform: translateY(0);
  }
  body.sponsors-page.show-stickybar { padding-bottom: 80px; }
  .sp-mobile-stickybar .info {
    display: flex; flex-direction: column; gap: 2px;
    flex: 1 1 auto; min-width: 0;
  }
  .sp-mobile-stickybar .eyebrow {
    font-family: 'JetBrains Mono', monospace;
    font-size: 9.5px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--gilt, #B68A3E);
  }
  .sp-mobile-stickybar .deadline {
    font-family: 'Newsreader', Georgia, serif;
    font-style: italic;
    font-size: 14px;
    color: var(--ink, #1A1208);
  }
  .sp-mobile-stickybar .cta {
    flex: 0 0 auto;
    background: linear-gradient(135deg, #C99A47 0%, #B68A3E 50%, #8a6620 100%);
    color: #FBF5E5;
    text-decoration: none;
    padding: 12px 16px;
    border-radius: 3px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 10.5px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    font-weight: 600;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    box-shadow: 0 2px 0 #6f5117, 0 6px 14px -3px rgba(40,28,12,0.35);
  }
}


/* ============================================================
   SPONSORS — audience stats grid (phone)
   ============================================================ */
@media (max-width: 640px) {
  /* The .audience-grid stats (~620 / 32 / etc) were rendering in
     a tight column with number + caption running together. Force
     2-col grid with clear hierarchy: big italic number above,
     monospace caps caption below. */
  .audience-grid {
    display: grid !important;
    grid-template-columns: repeat(2, 1fr) !important;
    gap: 12px !important;
    margin: 16px 0 !important;
  }
  .aud-stat {
    display: flex !important;
    flex-direction: column !important;
    align-items: flex-start !important;
    padding: 14px 12px !important;
    background: rgba(244, 236, 218, 0.30) !important;
    border: 1px solid rgba(40, 28, 12, 0.10) !important;
    border-radius: 3px !important;
    min-height: 88px !important;
  }
  .aud-stat .n {
    font-family: 'Newsreader', Georgia, serif !important;
    font-style: italic !important;
    font-weight: 300 !important;
    font-size: 28px !important;
    line-height: 1 !important;
    color: var(--gilt, #B68A3E) !important;
    margin: 0 0 6px !important;
    display: block !important;
    width: auto !important;
    max-width: 100% !important;
    white-space: normal !important;
  }
  .aud-stat .k {
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 9.5px !important;
    letter-spacing: 0.18em !important;
    text-transform: uppercase !important;
    color: var(--muted, #6B5A36) !important;
    line-height: 1.4 !important;
    margin: 0 !important;
    width: 100% !important;
  }
  /* audience-mix list below the stats */
  .audience-mix {
    margin-top: 20px !important;
  }
  .audience-mix h4 {
    font-size: 14px !important;
    margin-bottom: 12px !important;
  }
  .audience-mix ul {
    padding-left: 18px !important;
  }
  .audience-mix li {
    font-size: 14px !important;
    line-height: 1.55 !important;
    margin-bottom: 6px !important;
  }
}


/* ============================================================
   SPONSORS — "Already in the room" patron list overflow (phone)
   ============================================================ */
@media (max-width: 640px) {
  /* The Cisco·NetApp·AWS·... patron name strip was rendering as
     one nowrap line that overflowed. Allow line wrapping AT the
     bullet separators only — don't break inside multi-word names
     like "Safe Logic" or "Bouncy Castle". */
  [class*="already-in-the-room"],
  [class*="patron-line"],
  [class*="patron-roster-line"],
  [class*="sp-patron-stream"],
  .patrons-frontispiece + *,
  .patrons-frontispiece p {
    white-space: normal !important;
    word-break: keep-all !important;
    overflow-wrap: normal !important;
    hyphens: none !important;
    text-overflow: clip !important;
    overflow: visible !important;
    max-width: 100% !important;
    line-height: 1.7 !important;
  }
  /* Keep multi-word patron names together by treating non-breaking
     spaces as their natural delimiter — relies on author's markup
     using regular spaces inside names. */
  /* If the patron list is in a <ul> with inline-block items */
  [class*="patron-stream"] li,
  .patron-stream li {
    display: inline !important;
    white-space: normal !important;
  }
}


/* ============================================================
   SPONSORS — patron list fix + tier ledger accordion (phone)
   ============================================================ */
@media (max-width: 640px) {
  /* .pf-sub patron list — apply keep-all/normal wrap explicitly so
     "Bouncy Castle", "Safe Logic" etc never break mid-name. */
  .pf-sub,
  div.pf-sub {
    white-space: normal !important;
    word-break: keep-all !important;
    overflow-wrap: normal !important;
    hyphens: none !important;
    line-height: 1.7 !important;
    max-width: 100% !important;
    overflow: visible !important;
    text-align: center !important;
  }

  /* === TIER LEDGER as compact accordion ===
     Each .tl-card / .tier-card collapses to a single tappable row
     on phone: tier name + price + expand arrow. The deliverables
     list expands inline when tapped. */
  .tier-ledger,
  .tier-cards,
  .tier-ledger-grid {
    display: flex !important;
    flex-direction: column !important;
    grid-template-columns: none !important;
    gap: 0 !important;
    padding: 0 !important;
    margin: 16px 0 !important;
    overflow: visible !important;
    border-top: 1px solid var(--rule-2, rgba(40,28,12,0.18)) !important;
    border-bottom: 1px solid var(--rule-2, rgba(40,28,12,0.18)) !important;
  }
  .tier-ledger::-webkit-scrollbar { display: none; }
  .tier-ledger::after { display: none !important; }
  
  /* NOTE: Selectors are scoped to descendants of accordion containers
     (.tier-ledger, .tier-cards, .tier-ledger-grid). Bare `.tier-card`
     /`.tl-card` selectors used to swallow the index page's
     `.tickets-grid > .tier-card` swipe gallery, squashing those cards
     to ~63px wide and breaking the swipe. */
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tier-card,
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tl-card,
  .tier-ledger > article,
  .tier-ledger > .tl-tier {
    flex: 1 1 auto !important;
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
    border: 0 !important;
    border-bottom: 1px solid var(--rule-2, rgba(40,28,12,0.14)) !important;
    background: transparent !important;
    box-shadow: none !important;
    border-radius: 0 !important;
    scroll-snap-align: none !important;
    overflow: hidden !important;
    /* Collapsed by default — only the tier-name + price visible */
    max-height: 80px !important;
    transition: max-height 360ms ease !important;
    position: relative;
  }
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tier-card.is-open,
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tl-card.is-open {
    max-height: 2200px !important;
  }
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tier-card:last-of-type,
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tl-card:last-of-type {
    border-bottom: 0 !important;
  }
  /* Make the entire card tappable; show + indicator */
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tier-card,
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tl-card {
    cursor: pointer;
  }
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tier-card::after,
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tl-card::after {
    content: '+';
    position: absolute;
    top: 28px;
    right: 16px;
    width: 28px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--rule-2, rgba(40,28,12,0.22));
    border-radius: 50%;
    font-family: 'JetBrains Mono', monospace;
    font-size: 16px;
    color: var(--gilt, #B68A3E);
    transition: transform 220ms ease, background 220ms ease;
    z-index: 5;
    pointer-events: none;
  }
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tier-card.is-open::after,
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tl-card.is-open::after {
    content: '−';
    background: var(--ink, #1A1208);
    color: var(--paper, #FBF5E5);
    border-color: var(--ink, #1A1208);
  }
  /* The "head" of each card (tier name + price) stays visible.
     The "body" (deliverables, fine print) hides until expanded. */
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tier-card > *,
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tl-card > * {
    padding-left: 16px !important;
    padding-right: 56px !important;
  }
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tier-card .tier-head,
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tier-card .tc-head,
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tl-card .tl-head,
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tier-card > h3,
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tl-card > h3 {
    padding: 22px 56px 8px 16px !important;
    margin: 0 !important;
    font-family: 'Newsreader', Georgia, serif !important;
    font-style: italic !important;
    font-size: 22px !important;
    line-height: 1.1 !important;
  }
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tier-card .tier-price,
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tier-card .tc-price,
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tl-card .tl-price,
  :where(.tier-ledger, .tier-cards, .tier-ledger-grid) .tier-card .price {
    padding: 0 56px 18px 16px !important;
    margin: 0 !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 11px !important;
    letter-spacing: 0.18em !important;
    text-transform: uppercase !important;
    color: var(--gilt, #B68A3E) !important;
  }
}


/* ============================================================
   SPONSORS — .sp-signed-list patron-name nowrap (phone)
   The patron list uses <span class="n">Bouncy Castle</span>
   separated by <span class="d">·</span>. Each name span needs
   white-space: nowrap so "Bouncy Castle" never breaks inside.
   ============================================================ */
@media (max-width: 640px) {
  .sp-signed-list,
  p.sp-signed-list {
    white-space: normal !important;
    word-break: keep-all !important;
    overflow-wrap: normal !important;
    line-height: 1.8 !important;
    text-align: center !important;
    max-width: 100% !important;
  }
  .sp-signed-list .n {
    white-space: nowrap !important;
    display: inline-block !important;
  }
  .sp-signed-list .d {
    white-space: nowrap !important;
    padding: 0 6px !important;
    display: inline-block !important;
  }
}


/* ============================================================
   UNIFIED SWIPE-HINT (phone)
   Many horizontal-scroll rows carry a "swipe →" chip but use
   `flex: 0 0 auto; align-self: center` positioning, which places
   the chip at the end of the row — invisible until the user has
   already scrolled past everything. The whole point of the hint
   is to TELL them they can scroll, so it has to be visible from
   the start.
   
   This block re-stamps every known swipe-row's ::after as a
   `position: sticky; right: 0` chip so it floats over the right
   edge of the visible viewport regardless of scroll position.
   ============================================================ */
@media (max-width: 640px) {
  .tickets-grid::after,
  .offer-grid::after,
  .once-triptych::after,
  .e03-strip::after,
  .ph-plenary-grid::after,
  .ph-plenary-stack::after,
  .evenings-grid::after,
  .tut-grid::after,
  .cfp-process-grid::after,
  .m-surfaces::after,
  .m-audience::after,
  .pt-who-grid::after,
  .sp-mobile-tabstrip::after,
  *:has(> .cfp-track-card)::after {
    content: 'swipe →' !important;
    position: sticky !important;
    right: 6px !important;
    left: auto !important;
    /* Sit ABOVE the card content, not on top of it. The chip floats
       at the top edge of the scroll row and follows the right edge
       as the user swipes. Negative top so it clears any section
       heading text inside the row's content area. */
    top: -22px !important;
    bottom: auto !important;
    align-self: flex-start !important;
    flex: 0 0 auto !important;
    margin-left: -68px !important;
    margin-top: 0 !important;
    padding: 6px 12px !important;
    font-family: 'JetBrains Mono', monospace !important;
    font-size: 9.5px !important;
    letter-spacing: 0.22em !important;
    text-transform: uppercase !important;
    background: rgba(40,28,12,0.88) !important;
    color: #F4ECDA !important;
    border-radius: 14px !important;
    pointer-events: none !important;
    display: inline-flex !important;
    align-items: center !important;
    height: 26px !important;
    line-height: 1 !important;
    z-index: 5 !important;
    visibility: visible !important;
    opacity: 0.92 !important;
    animation: swipeHintFloat 1.8s ease-in-out infinite !important;
  }
  /* The sponsors page tab-strip is short and horizontal — it doesn't
     need a tall floating chip, just a small "→ more" cue inline. */
  .sp-mobile-tabstrip {
    position: relative;
  }
  /* The sponsors tab-strip is a thin horizontal pill row sitting
     sticky under the topnav. Any chip placed inside overlaps the
     tabs themselves (Patrons / Funds). The cut-off final tab is its
     own visual cue, so suppress the swipe chip on this strip. */
  .sp-mobile-tabstrip::after {
    display: none !important;
    content: '' !important;
  }
}


/* ============================================================
   SPEAKER PROFILE — "play me!" scribble note (phone)
   The hand-drawn marginalia (.reel-card-note) is positioned
   absolutely below the clapperboard reel. On desktop it sits
   in the margin pointing at the reel. On phone (Galaxy S10
   and similar) the bio metadata column wraps directly beneath
   the reel, and the scribble lands ON TOP of the "Co-author,
   SSLeay · President, OpenSSL Corporation" text. Hide it on
   phone — the clapperboard itself is a clear "tap me" cue.
   ============================================================ */
@media (max-width: 640px) {
  .reel-card-note {
    display: none !important;
  }
}
