/* =============================================================
   teamwiener.com — single-page redesign
   Palette, type, reset, then shared components, then per-section rules.
   Every screen of the site is one top-level <section> tagged with a
   scoping class like .s-hero, .s-subnav, .s-welcome, etc. so its
   local selectors (.head, .grid, .photo, ...) don't collide with
   identically-named selectors in another section.
   ============================================================= */

:root {
  --ink: #1a1410;
  --ink-soft: #1a1410cc;
  --ink-mute: #1a141099;
  --ink-blue: #092839;     /* dark blue from the Team Wiener logo; used for links + primary buttons */
  --cream: #FBF2E8;
  --cream-deep: #F5E4D0;
  --paper: #FDFBF7;
  --orange: #ED7A3D;
  --orange-deep: #D45A20;
  --yellow: #FFC83D;
  --navy: #14213D;
  --blue: #1E49C7;

  /* Systematic section spacing.
     --section-pad-y        Full separation between unrelated sections.
     --section-pad-y-tight  Shared-edge padding for a grouped PAIR of
                            sections that should read as one unit
                            (e.g. welcome → countdowns, events → calendar).
                            Both sides of the seam use this value, so the
                            total gap between the pair is ~2×.
     --section-pad-x        Horizontal gutter used by every section. */
  --section-pad-y: clamp(56px, 7vw, 104px);
  --section-pad-y-tight: clamp(16px, 2vw, 32px);
  --section-pad-x: clamp(20px, 4vw, 64px);
}

/* ============================================================
   RESPONSIVE BREAKPOINTS
   The whole site uses exactly two media-query widths so layouts
   transition predictably and consistently. CSS doesn't support
   custom properties inside @media expressions (yet), so the
   numbers are inlined wherever needed; this comment is the
   source-of-truth definition.

     Desktop                  > 960px
     Tablet                  ≤ 960px   →  @media (max-width:960px)
     Phone                   ≤ 600px   →  @media (max-width:600px)

   Pick "tablet" for any rule that should fire on tablet AND phone
   (most multi-column → single-column collapses). Pick "phone" for
   rules that should ONLY fire on phones (text re-alignment,
   smaller logos, switching to a horizontal carousel, etc.).

   If you find yourself wanting a third breakpoint, first check
   whether the rule can be re-expressed with `clamp()`/grid so it
   scales smoothly between the two existing breaks instead of
   adding a new step.
   ============================================================ */

/* Reset */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: 'DM Sans', system-ui, sans-serif;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; display: block; }
a { color: var(--ink-blue); }

/* Smooth scroll for subnav anchors */
html { scroll-behavior: smooth; }


/* ============================================================
   SHARED COMPONENTS
   Reusable building blocks used across sections, declared up
   front so per-section rules only override what they need.
   ============================================================ */

/* Default section heading. Individual sections may bump the size or
   line-height, but font, color, and reset are uniform site-wide. */
h2 { font-family:'Archivo Black',sans-serif;
    font-size:clamp(32px,4.5vw,52px);
    line-height:1; letter-spacing:-0.02em;
    margin:0;
    color:var(--ink-blue); }

/* Highlighter band emphasis for a span inside an <h2>. Wrap a few
   words in <span class="u"> to apply the canonical thick yellow band. */
h2 .u { background:linear-gradient(transparent 60%, var(--yellow) 60% 90%, transparent 90%);
    padding:0 4px; }

/* Default body paragraph. Used site-wide for any content <p>: same
   size, line-height, color, max-width, and alignment in every section
   so paragraphs read identically whether they're under an H1, H2, in a
   captain blurb, or beside a photo. Special-purpose paragraphs override
   this via class (.events-status loader, .tagline in the orange footer)
   or scoping (.s-bio .prose for the long-form Chinese bio body, plus
   the html[lang="zh-Hant"] welcome lede which stays centered to match
   that page's stacked hero). --ink-soft is the canonical body color;
   the dimmer --ink-mute is reserved for muted metadata, not prose. */
p { margin:0;
    font-size:clamp(15px,1.1vw,17px);
    line-height:1.55;
    color:var(--ink-soft);
    max-width:54ch;
    text-align:left; }

/* Centered head modifier. Add `centered` alongside `.head` on sections
   whose title block sits above a full-width content area (visit,
   contacts, resources) so the H2 and its supporting <p> read as a
   centered banner. Sections with split layouts where the title shares
   a row with a photo/video (welcome, captain, suggest, newsletter) or
   with a side button (events) leave it off and stay left-aligned.

   Self-contained: redeclares the flex-column layout and inner gap so
   it works even on `.head` blocks that don't otherwise set a flex
   layout. The explicit text-align on h1/h2/p re-centers their text
   over the global `p { text-align:left }` default, and `margin:0 auto`
   on the head itself keeps the centered block centered on the page. */
.head.centered { display:flex; flex-direction:column;
    align-items:center; gap:12px;
    margin-left:auto; margin-right:auto; }
.head.centered > h1,
.head.centered > h2,
.head.centered > p { text-align:center; }

/* Phone override: full-width centered title banners revert to
   left-aligned so headings line up with the rest of the (left-aligned)
   page content on narrow screens. The desktop/tablet centered layout
   reads as a deliberate banner above wide content; on phones it just
   looks disconnected from the body copy below it. */
@media (max-width:600px) {
  .head.centered { align-items:flex-start;
      margin-left:0; margin-right:0; }
  .head.centered > h1,
  .head.centered > h2,
  .head.centered > p { text-align:left; }
}

/* Framed feature box. Cream-deep field, ink-blue stroke, offset
   ink-blue drop shadow — used for portraits, photos, video media,
   and the contacts map frame. Add `framed--accent` to swap the
   shadow color to orange. */
.framed { background:var(--cream-deep);
    border:3px solid var(--ink-blue);
    box-shadow:10px 10px 0 var(--ink-blue);
    overflow:hidden; }
.framed--accent { box-shadow:10px 10px 0 var(--orange); }

/* Striped top accent. Shared between the footer (homepage canonical
   look), the events section, and the chinese-page bio section. Each
   target also sets position:relative + overflow:hidden on its own
   section; this rule just paints the band. */
.s-footer::before,
.s-events::before,
.s-bio::before {
  content:""; position:absolute; top:0; left:0; right:0; height:6px;
  background:repeating-linear-gradient(90deg,
    var(--ink) 0 24px, var(--yellow) 24px 48px);
}


/* ============================================================
   COMPONENT: button
   .btn = base. .btn.primary = orange bg + blue text.
   .btn.secondary = white bg + blue text.
   ============================================================ */
.btn { display:inline-flex; align-items:center; gap:10px;
    padding:14px 22px;
    font-family:'Archivo Black',sans-serif;
    font-size:14px; letter-spacing:.06em; text-transform:uppercase;
    text-decoration:none;
    border:2px solid var(--ink-blue);
    box-shadow:4px 4px 0 var(--ink-blue);
    transition:transform .1s, box-shadow .1s;
    cursor:pointer;
    width:max-content; max-width:100%; }
.btn:hover { transform:translate(-2px,-2px); box-shadow:6px 6px 0 var(--ink-blue); }
.btn.primary { background:var(--orange); color:#fff; }
.btn.secondary { background:#fff; color:var(--ink-blue); }
/* Arrow glyph for buttons that lead to a different page or external site.
   Add as last child: <span class="arrow" aria-hidden="true">➔</span>
   Uses U+2794 "Heavy Wide-Headed Rightwards Arrow" so the weight matches
   Archivo Black without depending on the typeface's own arrow glyph. */
.btn .arrow { display:inline-flex; align-items:center; justify-content:center;
    font-size:1.05em; line-height:1;
    transition:transform .15s; }
.btn:hover .arrow { transform:translateX(3px); }


/* Shared inline email link: highlighter underline that animates to a
   full fill on hover. Used by team cards (and historically the captain
   section), so it's declared globally rather than scoped. */
.email-link { font-family:'JetBrains Mono',monospace;
    font-weight:700;
    font-size:.92em;
    letter-spacing:.01em;
    color:var(--ink-blue);
    text-decoration:none;
    background-image:linear-gradient(var(--yellow), var(--yellow));
    background-repeat:no-repeat;
    background-position:0 92%;
    background-size:100% 24%;
    padding:0 3px;
    word-break:break-word;
    transition:background-size .25s ease, background-position .25s ease, color .25s ease; }
.email-link:hover,
.email-link:focus-visible { background-size:100% 100%;
    background-position:0 0;
    color:var(--ink-blue); }


/* ============================================================
   SECTION: top banner
   Full-width utility bar above the hero on the homepage that
   points visitors at scottwiener.com (the official campaign site).
   The element itself is the <a>, so the entire dark blue strip is
   the click target. Not used on the Chinese landing page.
   ============================================================ */
.s-topbanner { display:block; background:var(--ink-blue); color:#fff;
    padding:13px clamp(16px,3vw,32px);
    text-align:center;
    font-size:16px; line-height:1.5;
    text-decoration:none;
    transition:color .25s ease; }
.s-topbanner:hover { color:var(--yellow); }
.s-topbanner:focus-visible { outline:2px solid var(--yellow); outline-offset:-3px; }
.s-topbanner .arrow { display:inline-block; margin-left:6px;
    font-size:.95em; transform:translateY(-1px); }
@media (max-width:600px) {
  .s-topbanner { font-size:14px; padding:11px 14px; letter-spacing:0; }
}


/* ============================================================
   SECTION: hero
   ============================================================ */
.s-hero { position:relative;
    width:100%;
    padding:clamp(32px,6vw,120px) 0;
    background:var(--orange);
    color:var(--ink);
    overflow:hidden;
    display:flex; flex-direction:column; justify-content:center; }
.s-hero::before { content:"";
    position:absolute; inset:0;
    background-image:radial-gradient(#1a141040 1px,transparent 1.5px);
    background-size:14px 14px;
    opacity:.25;
    pointer-events:none; }
.s-hero .logo { position:relative; z-index:2;
    display:block;
    width:50vw;
    max-width:2400px;
    height:auto;
    margin:0 auto; }
@media (max-width:600px) {
  .s-hero .logo { width:90vw; }
}


/* ============================================================
   SECTION: subnav
   ============================================================ */
.s-subnav .bar { width:100%;
    background:var(--cream);
    display:flex; align-items:center; justify-content:center;
    padding:0 clamp(16px,4vw,48px);
    overflow-x:auto;
    overflow-y:hidden;
    /* Hidden scrollbar by default on desktop. The mobile media query below
       swaps to an always-visible, branded horizontal scrollbar. */
    scrollbar-width:none; }
.s-subnav .bar::-webkit-scrollbar { display:none; }
.s-subnav .links { display:flex; gap:clamp(20px,3.2vw,44px); align-items:center;
    flex-wrap:nowrap; white-space:nowrap; }
.s-subnav .links a { font-family:'Archivo Black',sans-serif;
    font-size:clamp(13px,1.25vw,16px);
    letter-spacing:.08em; text-transform:uppercase;
    color:var(--ink-blue); text-decoration:none;
    display:inline-flex; align-items:center;
    padding:clamp(22px,2.2vw,30px) 2px;
    transition:color .15s; }
.s-subnav .links a:hover { color:var(--orange-deep); }
.s-subnav .links a.ext::after { content:" ↗"; margin-left:4px; color:var(--orange-deep); }
/* Archivo Black has no CJK glyphs, so the Chinese link falls back to the
   system sans. Bumping the weight makes that fallback render heavy enough
   to match the visual mass of the Latin items in Archivo Black. */
.s-subnav .links a:lang(zh) { font-weight:900; }
/* Custom scroll indicator (rendered as a sibling of `.bar`). Hidden by
   default; only the mobile media query below makes it visible — desktop
   never overflows and doesn't need it. */
.s-subnav .bar-scroll { display:none; }
@media (max-width:600px) {
  .s-subnav .bar { justify-content:flex-start; }
  /* The custom scrollbar adds a 4px band of visual weight below the bar,
     which makes the link text read as off-center against the combined
     (bar + track) block. Shift the vertical padding so text recenters. */
  .s-subnav .links a { padding-top:calc(clamp(22px,2.2vw,30px) + 4px);
      padding-bottom:clamp(22px,2.2vw,30px); }
  /* iOS Safari ignores `::-webkit-scrollbar` styling and only flashes the
     native overlay scrollbar mid-scroll, so we paint our own. The track is
     always visible; the thumb's width and offset are kept in sync with the
     bar's `scrollLeft` by the subnav-scroll IIFE in app.js. */
  .s-subnav .bar-scroll { display:block; position:relative;
      height:4px;
      background:rgba(9,40,57,.10);
      margin:0; }
  .s-subnav .bar-thumb { position:absolute; top:0; left:0;
      height:100%;
      background:var(--orange);
      width:30%;
      transform:translateX(0);
      will-change:transform,width; }
}


/* ============================================================
   SECTION: welcome
   ============================================================ */
.s-welcome { background:var(--paper);
    padding:var(--section-pad-y) var(--section-pad-x) var(--section-pad-y-tight);
    display:flex; flex-direction:column;
    position:relative; overflow:hidden; }
.s-welcome::before { content:""; position:absolute; top:-40px; right:-40px;
    width:200px;
    background:radial-gradient(#ED7A3D20 1.5px,transparent 2px);
    background-size:12px 12px;
    pointer-events:none; }
.s-welcome .grid { display:grid;
    grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);
    gap:clamp(24px,4vw,56px);
    align-items:stretch;
    max-width:1160px; margin:0 auto; width:100%; }
.s-welcome .portrait { position:relative;
    width:100%;
    /* 16/9 matches the native aspect of media/scott_welcome.mp4 (and the
       poster image) so the video fills the frame edge-to-edge with no
       cropping. If a future clip ships at a different aspect, update this
       value and the poster to match. */
    aspect-ratio:16/9;
    min-height:clamp(208px,27vw,368px);
    background:#000; /* shows behind the poster while it's loading */ }
.s-welcome .portrait .candidate-video { position:absolute; inset:0;
    width:100%; height:100%;
    /* cover (not contain) because the frame already matches the video's
       16:9 aspect — cover guarantees no thin letterbox bands appear from
       sub-pixel rounding. */
    object-fit:cover;
    display:block;
    background:#000; }
/* Still-image variant of the welcome portrait, used by the Chinese
   landing page (/meet-scott-chinese/) which keeps the static photo
   instead of the homepage video. The html[lang="zh-Hant"] overrides
   further down tweak `object-position` per breakpoint. */
.s-welcome .portrait .candidate { position:absolute; inset:0;
    width:100%; height:100%;
    object-fit:cover;
    object-position:85% 18%;
    display:block; }
/* Centered orange "play" button that overlays the welcome video. Inherits
   the .btn.primary palette (orange fill, ink-blue stroke + offset shadow)
   so it reads as a primary CTA, but overrides padding and shape to a
   round play badge. The welcome-video IIFE in app.js toggles `is-hidden`
   when the video starts and removes it again on pause/end so visitors
   can replay. The transform values keep the button visually centered
   (translate(-50%, -50%)) and the hover rule re-applies that centering
   together with the standard btn -2px lift, since the base .btn:hover
   rule's transform would otherwise override our centering. */
.s-welcome .welcome-play { position:absolute;
    top:50%; left:50%;
    transform:translate(-50%, -50%);
    z-index:2;
    width:clamp(72px, 9vw, 96px);
    height:clamp(72px, 9vw, 96px);
    padding:0;
    border-radius:50%;
    font-size:clamp(28px, 3.4vw, 38px);
    line-height:1;
    /* The ▶︎ glyph is left-weighted; nudge it right so it sits visually
       centered in the round badge. */
    text-indent:.18em;
    justify-content:center; }
.s-welcome .welcome-play:hover { transform:translate(calc(-50% - 2px), calc(-50% - 2px));
    box-shadow:6px 6px 0 var(--ink-blue); }
.s-welcome .welcome-play:focus-visible { outline:3px solid var(--yellow);
    outline-offset:3px; }
.s-welcome .welcome-play.is-hidden { display:none; }

/* Thin orange playback progress bar pinned to the bottom edge of the
   video frame. Width is set inline by the welcome-video IIFE in app.js
   on every `timeupdate` (currentTime / duration × 100%); the short
   linear transition smooths over the ~250ms cadence at which the
   browser fires `timeupdate`. The bar starts at 0% (so it's invisible
   over the poster), grows to 100% at the end of the clip, and the
   IIFE briefly drops the transition when resetting to 0% on replay so
   we never show a visible backwards animation. */
.s-welcome .welcome-progress { position:absolute;
    left:0; bottom:0;
    height:4px; width:0;
    background:var(--orange);
    z-index:2;
    pointer-events:none;
    transition:width .18s linear; }
.s-welcome .intro { display:flex; flex-direction:column; gap:20px; justify-content:center; }
.s-welcome .h1 { font-family:'Archivo Black',sans-serif;
    font-size:clamp(36px,5.5vw,60px);
    line-height:.98; letter-spacing:-0.02em; margin:0;
    color:var(--ink-blue); }
.s-welcome .h1 em { font-style:normal; color:var(--orange); display:inline-block;
    background:var(--ink-blue); padding:0 14px; transform:skewX(-6deg); }
.s-welcome .h1 em span { display:inline-block; transform:skewX(6deg); }
/* The welcome <p class="lede"> intentionally has no per-section font /
   color rules — it inherits the global `p` defaults so the hero
   subtitle reads identically to every other section's body copy. The
   .lede class is kept as a hook for the html[lang="zh-Hant"] override
   below (which restores centered alignment for the Chinese hero). */
@media (max-width:960px) {
  .s-welcome .grid { grid-template-columns:1fr; gap:28px; }
  /* Stacked layout: portrait spans the full content column at its native
     16:9 aspect, so height follows width — no max-height cap, no min. */
  .s-welcome .portrait { min-height:0; }
}


/* ============================================================
   SECTION: countdowns
   ============================================================ */
.s-countdowns { background:var(--paper);
    padding:var(--section-pad-y-tight) var(--section-pad-x) var(--section-pad-y);
    display:flex; align-items:center; }
.s-countdowns .countdown { display:grid; grid-template-columns:1fr 1fr;
    gap:clamp(24px,5vw,72px);
    max-width:1160px; margin:0 auto; width:100%; }
.s-countdowns .cd-card { position:relative;
    background:#fff;
    border:3px solid var(--ink-blue);
    padding:clamp(16px,2vw,24px);
    display:flex; flex-direction:column; gap:4px;
    box-shadow:8px 8px 0 var(--ink-blue);
    overflow:hidden; }
.s-countdowns .cd-label { font-family:'JetBrains Mono',monospace;
    font-size:12px; letter-spacing:.18em; text-transform:uppercase;
    color:var(--orange-deep);
    display:flex; align-items:center; gap:8px; }
.s-countdowns .cd-label::before { content:"●"; font-size:10px; }
.s-countdowns .cd-days { font-family:'Archivo Black',sans-serif;
    font-size:clamp(44px,6.4vw,76px);
    line-height:1; color:var(--orange); letter-spacing:-0.03em; }
.s-countdowns .cd-days .unit { font-size:clamp(14px,1.3vw,18px);
    color:var(--ink-blue); letter-spacing:0; margin-left:6px; }
.s-countdowns .cd-date { font-size:13px; font-weight:500;
    color:var(--ink-mute); margin-top:2px; }
@media (max-width:600px) {
  .s-countdowns .countdown { grid-template-columns:1fr; }
}


/* ============================================================
   SECTION: captain
   ============================================================ */
.s-captain { background:var(--cream);
    padding:var(--section-pad-y) var(--section-pad-x);
    position:relative; overflow:hidden; }
.s-captain .grid { max-width:1200px; margin:0 auto;
    display:grid;
    /* Portrait 9:16 video on the right; text gets the extra width so the
       tall video column doesn't push the grid too wide. */
    grid-template-columns:minmax(280px,2.6fr) minmax(200px,1fr);
    gap:clamp(24px,4vw,56px);
    align-items:center;
    padding-top:clamp(12px,2vw,24px); }
.s-captain .text { display:flex; flex-direction:column; gap:20px; }
.s-captain h2 { font-size:clamp(34px,5vw,54px); line-height:.98; }
.s-captain .ctas { display:flex; gap:12px; flex-wrap:wrap; margin-top:6px; }
.s-captain .media { position:relative;
    /* Matches the native 9:16 aspect of captains-story.mp4 so the video
       fills the frame exactly — no top/bottom cropping. */
    aspect-ratio:9/16;
    background:var(--ink); }
.s-captain .captain-video { width:100%; height:100%;
    /* cover (not contain) because the frame already matches the video's
       9:16 aspect exactly. contain can reveal 1–2px of the dark frame
       background above/below from sub-pixel rounding; cover eliminates
       that gap. If a future clip has a different aspect ratio, update
       .s-captain .media's aspect-ratio to match and cover will continue
       to fill edge-to-edge without cropping. */
    object-fit:cover;
    display:block; }
@media (max-width:960px) {
  .s-captain .grid { grid-template-columns:1fr; gap:28px; }
  /* Stacked layout: the 9:16 frame gets tall quickly at large widths, so
     cap it narrower (≈44% of viewport, 240px max) to keep the video
     from dominating the stacked screen. */
  .s-captain .media { width:44%; max-width:240px; margin:0 auto; }
}


/* ============================================================
   SECTION: events
   ============================================================ */
.s-events { background:var(--cream);
    padding:var(--section-pad-y) var(--section-pad-x) var(--section-pad-y-tight);
    position:relative; overflow:hidden; }
.s-events .head { max-width:1200px; margin:0 auto clamp(24px,3vw,40px);
    display:flex; align-items:end; justify-content:space-between;
    gap:24px; flex-wrap:wrap; }
.s-events .grid { max-width:1200px; margin:0 auto;
    display:grid;
    grid-template-columns:repeat(3, minmax(0,1fr));
    gap:clamp(16px,2vw,24px); }
@media (max-width:960px) {
  .s-events .grid { grid-template-columns:1fr 1fr; }
}
@media (max-width:600px) {
  .s-events .grid { grid-template-columns:repeat(6, 82vw);
      overflow-x:auto;
      scroll-snap-type:x mandatory;
      padding-bottom:12px;
      scrollbar-width:thin; }
  .s-events .grid > * { scroll-snap-align:start; }
}
.s-events .card { display:flex; flex-direction:column;
    border:3px solid var(--ink-blue);
    background:#fff;
    overflow:hidden; }
/* Flyer is the event's featured graphic from Mobilize. Shown at its
   natural aspect ratio; a cream placeholder fills the box briefly while
   it loads. A thin ink-blue rule separates the graphic from the
   informational body below. */
.s-events .flyer { position:relative;
    background:var(--cream-deep);
    overflow:hidden;
    border-bottom:3px solid var(--ink-blue); }
.s-events .flyer img { display:block;
    width:100%; height:auto; }
/* Fallback tile rendered only when an event has no featured_image_url. */
.s-events .flyer--fallback { aspect-ratio:1/1;
    display:flex; align-items:center; justify-content:center;
    padding:24px;
    background:var(--orange); }
.s-events .flyer--fallback span { font-family:'Archivo Black',sans-serif;
    font-size:clamp(18px,2vw,26px);
    line-height:1.05;
    letter-spacing:-0.01em;
    text-transform:uppercase;
    text-align:center;
    color:var(--ink); }
.s-events .body { padding:16px;
    display:flex; flex-direction:column;
    gap:10px;
    flex:1; }
.s-events .when { font-family:'JetBrains Mono',monospace;
    font-size:11px; letter-spacing:.12em; text-transform:uppercase;
    color:var(--orange-deep);
    font-weight:700; }
.s-events .name { font-family:'Archivo Black',sans-serif;
    font-size:17px; line-height:1.15;
    letter-spacing:-0.01em; }
.s-events .loc { font-size:13px; color:var(--ink-mute);
    display:flex; align-items:center; gap:6px; }
.s-events .loc::before { content:""; width:10px; height:12px; flex-shrink:0;
    background:var(--orange);
    clip-path:path('M5 0 C 1.5 0 0 2.5 0 5 C 0 8 5 12 5 12 C 5 12 10 8 10 5 C 10 2.5 8.5 0 5 0 Z M5 3 A 2 2 0 1 1 5 7 A 2 2 0 1 1 5 3 Z'); }
/* Sign-up button inside an event card: stretch edge-to-edge along
   the bottom of .body so the button still reads as a prominent
   "click here" footer CTA. */
.s-events .body .btn { margin-top:auto;
    align-self:stretch;
    width:auto; max-width:none;
    justify-content:center; }
/* Status message shown inside #eventsGrid while Mobilize data is loading,
   empty, or errored. Spans the full grid so it reads centered. */
.s-events .events-status { grid-column:1 / -1;
    margin:0;
    padding:clamp(28px,4vw,56px) 12px;
    text-align:center;
    font-family:'JetBrains Mono',monospace;
    font-size:12px; letter-spacing:.15em; text-transform:uppercase;
    color:var(--ink-mute); }
.s-events .events-status.is-error { color:var(--orange-deep); }
.s-events .events-status a { color:var(--ink-blue); font-weight:700;
    text-decoration:underline; text-underline-offset:3px; }


/* ============================================================
   SECTION: calendar
   ============================================================ */
.s-calendar { background:var(--cream);
    padding:var(--section-pad-y-tight) var(--section-pad-x) var(--section-pad-y); }
.s-calendar .frame { max-width:1200px; margin:0 auto;
    background:#fff;
    border:3px solid var(--ink-blue);
    overflow:hidden; }
.s-calendar .frame-head { display:flex; align-items:center; justify-content:space-between;
    padding:14px 18px;
    background:var(--ink);
    color:var(--cream);
    border-bottom:3px solid var(--orange); }
.s-calendar .tabs { display:inline-flex; gap:0; align-items:center;
    background:#0f0b08; border:1.5px solid #FBF2E833; border-radius:2px;
    padding:2px; }
.s-calendar .tab { font-family:'JetBrains Mono',monospace;
    font-size:11px; letter-spacing:.15em; text-transform:uppercase;
    padding:6px 12px; border:0; background:transparent; color:var(--cream);
    cursor:pointer; appearance:none; font-weight:700; }
.s-calendar .tab:hover { background:#FBF2E815; }
.s-calendar .tab.active { background:var(--orange); color:var(--ink); }
.s-calendar .tab:focus-visible { outline:2px solid var(--yellow); outline-offset:2px; }
.s-calendar .fh-title { font-family:'Archivo Black',sans-serif;
    font-size:13px; letter-spacing:.08em; text-transform:uppercase;
    display:flex; align-items:center; gap:10px; }
.s-calendar .fh-title::before { content:"▦"; color:var(--orange); font-size:15px; }
.s-calendar .cal-embed { background:#fff; position:relative; }
.s-calendar .cal-embed iframe { display:block; width:100%; height:720px; border:0; }
.s-calendar .fh-foot { padding:14px 18px; background:var(--cream);
    display:flex; justify-content:space-between; align-items:center; gap:16px;
    border-top:2px solid var(--ink-blue);
    font-family:'JetBrains Mono',monospace; font-size:11px; letter-spacing:.10em; }
.s-calendar .fh-foot-blurb { display:inline-flex; align-items:center; gap:8px;
    color:var(--ink); text-transform:uppercase; font-weight:700; }
.s-calendar .add-cal { flex-shrink:0; }
@media (max-width:960px) {
  .s-calendar .frame-head { flex-wrap:wrap; gap:10px 14px; }
  .s-calendar .cal-embed iframe { height:600px; }
}
@media (max-width:600px) {
  .s-calendar .frame-head { padding:12px 14px; }
  .s-calendar .tab { padding:5px 9px; font-size:10px; letter-spacing:.10em; }
  .s-calendar .cal-embed iframe { height:480px; }
  .s-calendar .fh-foot { flex-direction:column; align-items:flex-start;
      text-align:left; gap:10px; padding:14px; }
  .s-calendar .fh-foot-blurb { justify-content:flex-start; font-size:10px; letter-spacing:.08em; }
  .s-calendar .add-cal { align-self:stretch; justify-content:center; }
}


/* ============================================================
   SECTION: suggest
   ============================================================ */
.s-suggest { background:var(--paper);
    padding:var(--section-pad-y) var(--section-pad-x);
    position:relative; overflow:hidden; }
.s-suggest::after { content:""; position:absolute; top:0; right:-20px;
    width:160px;
    background:radial-gradient(#ED7A3D40 1.5px,transparent 2px);
    background-size:14px 14px;
    opacity:.5;
    pointer-events:none; }
.s-suggest .grid { max-width:1160px; margin:0 auto;
    display:grid;
    grid-template-columns:minmax(0,1fr) minmax(0,1fr);
    gap:clamp(24px,4vw,56px);
    align-items:center;
    position:relative; z-index:1; }
.s-suggest .photo { position:relative;
    width:100%;
    aspect-ratio:3/2; }
.s-suggest .photo .event-photo { position:absolute; inset:0;
    width:100%; height:100%;
    object-fit:cover;
    /* Scott's face sits mid-horizontal, bottom third of the source photo —
       keep that region centered regardless of the container aspect ratio. */
    object-position:50% 78%;
    display:block; }
.s-suggest .head { display:flex; flex-direction:column; gap:14px; }
@media (max-width:960px) {
  .s-suggest .grid { grid-template-columns:1fr; gap:28px; max-width:720px; }
  .s-suggest .photo { aspect-ratio:16/9; max-height:29vh; }
  .s-suggest .photo .event-photo { object-position:50% 72%; }
}
@media (max-width:600px) {
  .s-suggest .photo { aspect-ratio:3/2; max-height:25vh; }
  .s-suggest .photo .event-photo { object-position:50% 70%; }
}


/* ============================================================
   SECTION: visit
   HQ map (left) + walk-in office hours table (right). The H2 + lede
   sit on top in the standard `.head` block; the two-column grid
   collapses to a single column at tablet width. Map is rendered by
   the visit-hq IIFE in app.js using the same Maps JS API loader as
   the district map; the schedule's current-day row is highlighted by
   the same IIFE based on JS Date#getDay().

   Background is cream to alternate against the paper `.s-suggest`
   above and the paper `.s-contacts` below — keeping the
   paper/cream/paper/cream rhythm continuous.
   ============================================================ */
.s-visit { background:var(--cream);
    padding:var(--section-pad-y) var(--section-pad-x);
    position:relative; overflow:hidden; }
.s-visit .head { max-width:1200px; margin:0 auto clamp(24px,3vw,40px);
    display:flex; flex-direction:column; gap:12px;
    position:relative; z-index:1; }
.s-visit .grid { max-width:1200px; margin:0 auto;
    display:grid;
    /* Map gets the wider column so the pin stays readable; schedule
       column auto-sizes to its content. `align-items:stretch` (the
       grid default) makes both items match the row's tallest natural
       height — typically the schedule, since the mapframe below uses
       flex to stretch its inner mapbox to fill whatever height the
       schedule sets. Net effect: map and schedule are exactly the
       same height in desktop mode. */
    grid-template-columns:minmax(0,1.4fr) minmax(0,1fr);
    gap:clamp(20px,3vw,40px);
    align-items:stretch;
    position:relative; z-index:1; }

/* Map frame mirrors the .s-contacts pattern: orange dot + monospace
   title in a dark header bar, followed by the actual map area.
   `display:flex` lets the mapbox fill all height left over after the
   mapbar; `position:relative` is the positioning context for the
   floating "Get Directions" CTA pinned to the bottom-right corner. */
.s-visit .mapframe { background:#fff;
    position:relative;
    display:flex; flex-direction:column; }
.s-visit .mapbar { display:flex; gap:12px; align-items:center;
    padding:12px 16px;
    background:var(--ink); color:var(--cream);
    border-bottom:3px solid var(--orange);
    font-family:'JetBrains Mono',monospace;
    font-size:11px; letter-spacing:.12em; text-transform:uppercase;
    flex:0 0 auto; }
.s-visit .mapbar .dot { width:10px; height:10px; border-radius:50%;
    background:var(--orange); border:1.5px solid var(--cream); }
.s-visit .mapbar-title { white-space:nowrap; overflow:hidden;
    text-overflow:ellipsis; }
.s-visit .mapbox { position:relative;
    /* min-height is intentionally smaller than the schedule's natural
       height so the schedule (not the map) drives the grid row's
       stretch height — that keeps the schedule card from gaining
       awkward whitespace at the bottom. The mapbox then `flex:1`s up
       to fill whatever height the schedule sets. */
    flex:1 1 0; min-height:clamp(240px, 24vw, 320px);
    background:#EEF1F4; overflow:hidden; }
.s-visit .hqmap { position:absolute; inset:0;
    width:100%; height:100%; border:0; display:block; }

/* Floating "Get Directions" CTA pinned to the map's bottom-right
   corner. The button keeps its standard ink-blue offset shadow, so we
   leave enough inset (clamp 14–22px) that the shadow stays well
   inside the .framed parent's `overflow:hidden` box. */
.s-visit .mapfloat { position:absolute;
    right:clamp(14px,1.6vw,22px);
    bottom:clamp(14px,1.6vw,22px);
    z-index:2; }

/* Google InfoWindow content for the HQ marker. Google appends the
   InfoWindow inside the map's pane (inside #hqMap inside .s-visit),
   so this scoped selector matches even though Google paints its own
   white-bubble chrome around it. */
.s-visit .hq-iw { color:var(--ink); padding:2px 2px 0;
    font-family:'DM Sans', system-ui, sans-serif;
    min-width:160px; }
.s-visit .hq-iw strong { display:block;
    font-family:'Archivo Black', sans-serif;
    font-size:13px; letter-spacing:-0.01em;
    color:var(--ink-blue);
    margin-bottom:3px; }
.s-visit .hq-iw span { display:block;
    font-family:'JetBrains Mono', monospace;
    font-size:12px; letter-spacing:.02em;
    color:var(--ink-mute); }

/* Schedule card. White background + ink-blue stroke + offset shadow
   from .framed; we just override the cream-deep fill so the rows pop.
   Padding + row spacing are tuned so the natural card height drives
   the grid row stretch (see `.mapbox` min-height note above) — keeps
   the table compact without trailing whitespace. */
.s-visit .schedule { background:#fff;
    padding:clamp(14px,1.6vw,20px) clamp(20px,2.2vw,30px) clamp(6px,1vw,12px); }
.s-visit .schedule-head { font-family:'Archivo Black',sans-serif;
    font-size:clamp(18px,1.6vw,22px);
    line-height:1; letter-spacing:-0.01em;
    color:var(--ink-blue);
    margin:0 0 clamp(8px,1.1vw,14px); }
.s-visit .sched { width:100%; border-collapse:collapse; }
.s-visit .sched tr { border-bottom:1px dashed #1a141033; }
.s-visit .sched tr:last-child { border-bottom:0; }
.s-visit .sched th,
.s-visit .sched td { padding:clamp(7px,0.9vw,11px) 6px; }
.s-visit .sched th { font-family:'Archivo Black',sans-serif;
    text-align:left;
    text-transform:uppercase; letter-spacing:.10em;
    font-size:12px;
    color:var(--ink-blue);
    font-weight:400; /* Archivo Black is already heavy */ }
.s-visit .sched td { font-family:'JetBrains Mono',monospace;
    text-align:right;
    font-size:13px; font-weight:500;
    color:var(--ink-soft);
    letter-spacing:.02em; }
.s-visit .sched td.closed { color:var(--ink-mute);
    text-transform:uppercase; letter-spacing:.14em;
    font-size:11px; font-weight:700; }

/* Highlight today's row. The visit-hq IIFE in app.js adds .is-today
   to whichever <tr data-day="…"> matches Date#getDay(). Yellow band
   matches the .h2 .u highlighter and the .email-link underline. */
.s-visit .sched tr.is-today { background:var(--yellow); }
.s-visit .sched tr.is-today th,
.s-visit .sched tr.is-today td { color:var(--ink); }
.s-visit .sched tr.is-today td.closed { color:var(--ink); }

@media (max-width:960px) {
  /* Stacked layout: drop the equal-height stretching since the grid is
     a single column. The mapbox needs an intrinsic height again, so
     swap flex:1 → aspect-ratio. */
  .s-visit .grid { grid-template-columns:1fr; max-width:720px; }
  .s-visit .mapbox { flex:initial; min-height:0; aspect-ratio:16/10; }
}
@media (max-width:600px) {
  .s-visit .schedule { box-shadow:6px 6px 0 var(--ink-blue); }
}


/* ============================================================
   SECTION: contacts
   Cream background to keep the cream(suggest)/paper(visit)/cream/paper
   alternation continuous through the lower half of the page.
   ============================================================ */
.s-contacts { background:var(--paper);
    padding:var(--section-pad-y) var(--section-pad-x) var(--section-pad-y-tight); }
.s-contacts .head { max-width:1200px; margin:0 auto clamp(24px,3vw,40px);
    display:flex; flex-direction:column; gap:12px; }
.s-contacts .mapframe { max-width:1200px; margin:0 auto;
    background:#fff; }
.s-contacts .mapbar { display:flex; gap:12px; align-items:center;
    flex-wrap:wrap;
    padding:12px 16px;
    background:var(--ink); color:var(--cream);
    border-bottom:3px solid var(--orange);
    font-family:'JetBrains Mono',monospace;
    font-size:11px; letter-spacing:.12em; text-transform:uppercase; }
.s-contacts .mapbar .dot { width:10px; height:10px; border-radius:50%;
    background:var(--orange); border:1.5px solid var(--cream); }
.s-contacts .mapbar-title { white-space:nowrap; }

/* Map address search: real <input> with a typeahead dropdown. The
   wrapper is `position:relative` so the absolutely-positioned results
   list sits flush against the input below the dark header. */
.s-contacts .map-search { position:relative;
    margin-left:auto;
    flex:1 1 320px; max-width:420px;
    display:flex; align-items:center; }
.s-contacts .map-search-icon { position:absolute; left:12px; top:50%;
    transform:translateY(-50%);
    font-size:16px; color:var(--ink-mute);
    pointer-events:none; }
.s-contacts .map-search input { width:100%;
    box-sizing:border-box;
    padding:10px 12px 10px 34px;
    height:38px;
    background:var(--cream); color:var(--ink);
    border:2px solid var(--cream);
    border-radius:2px;
    font-family:'JetBrains Mono',monospace;
    font-size:13px; letter-spacing:.02em;
    text-transform:none;
    outline:none;
    transition:border-color .15s, box-shadow .15s; }
.s-contacts .map-search input::placeholder { color:#1a141066;
    text-transform:none; letter-spacing:.02em; }
.s-contacts .map-search input:focus { border-color:var(--orange);
    box-shadow:0 0 0 3px #ED7A3D40; }
/* Drop the native cancel/clear button so it doesn't fight the icon. */
.s-contacts .map-search input::-webkit-search-cancel-button { -webkit-appearance:none; appearance:none; }

.s-contacts .map-search-results { position:absolute;
    top:calc(100% + 8px); left:0; right:0;
    list-style:none; margin:0; padding:4px;
    background:#fff; color:var(--ink);
    border:2px solid var(--ink-blue);
    box-shadow:4px 4px 0 var(--ink-blue);
    max-height:280px; overflow:auto;
    z-index:20;
    font-family:'DM Sans',sans-serif;
    text-transform:none; letter-spacing:0; }
.s-contacts .map-search-results li { padding:8px 10px;
    cursor:pointer;
    display:flex; flex-direction:column; gap:2px;
    border-radius:2px;
    font-size:13px; line-height:1.3; }
.s-contacts .map-search-results li.is-active,
.s-contacts .map-search-results li:hover { background:var(--yellow); }
.s-contacts .map-search-results .r-name { font-weight:700; color:var(--ink-blue); }
.s-contacts .map-search-results .r-context { font-size:11px; color:var(--ink-mute); }
.s-contacts .map-search-empty { padding:10px;
    font-size:12px; color:var(--ink-mute); cursor:default; }

.s-contacts .mapbox { position:relative;
    aspect-ratio:2/1;
    background:#EEF1F4;
    overflow:hidden; }
.s-contacts .mymap { position:absolute; inset:0;
    width:100%; height:100%;
    border:0; display:block; }

/* KML feature-click popup. Google's InfoWindow supplies the outer white
   chrome + close button; these rules style the body we inject into it
   (see buildPopupHtml in app.js). Monospace all-caps labels match the
   .mapbar header vocabulary. */
.s-contacts .map-popup { color:var(--ink); min-width:180px; padding:2px 2px 0; }
.s-contacts .map-popup .mp-row { display:flex; gap:10px;
    align-items:baseline;
    font-size:13px; line-height:1.45; margin-top:4px; }
.s-contacts .map-popup .mp-row:first-child { margin-top:0; }
.s-contacts .map-popup .mp-key { font-family:'JetBrains Mono',monospace;
    font-size:10px; letter-spacing:.12em; text-transform:uppercase;
    color:var(--ink-mute); min-width:80px; }
.s-contacts .map-popup .mp-val { font-weight:500; color:var(--ink-blue); }

/* On tablet and below, force the search onto its own row beneath the
   dot + title rather than letting them squish into a single line.
   `width:100%` is the reliable trigger for the wrap; without it Safari
   sometimes still tries to fit the input alongside the title. */
@media (max-width:960px) {
  .s-contacts .map-search { flex-basis:100%; width:100%;
      max-width:none; margin-left:0; }
}
@media (max-width:600px) {
  .s-contacts .mapbox { aspect-ratio:4/5; }
}


/* ============================================================
   SECTION: team
   ============================================================ */
.s-team { background:var(--paper);
    padding:var(--section-pad-y-tight) var(--section-pad-x) var(--section-pad-y); }
.s-team .head { max-width:1200px; margin:0 auto clamp(20px,3vw,36px);
    display:flex; align-items:end; justify-content:space-between;
    gap:18px; flex-wrap:wrap; }
.s-team .grid { max-width:1200px; margin:0 auto;
    display:grid;
    grid-template-columns:repeat(4,minmax(0,1fr));
    gap:clamp(14px,1.8vw,22px); }
@media (max-width:960px) {
  .s-team .grid { grid-template-columns:repeat(2,1fr); }
}
@media (max-width:600px) {
  .s-team .grid { grid-template-columns:1fr; }
}
.s-team .person { display:flex; flex-direction:column;
    background:#fff;
    border:2.5px solid var(--ink-blue);
    overflow:hidden; }
.s-team .avatar { aspect-ratio:4/3;
    background:repeating-linear-gradient(135deg,#F5E4D0 0 14px,#EDD2B4 14px 28px);
    position:relative;
    display:flex; align-items:end; justify-content:center;
    overflow:hidden;
    border-bottom:2.5px solid var(--ink-blue); }
.s-team .avatar img { position:absolute; inset:0;
    width:100%; height:100%;
    object-fit:cover; object-position:center 30%;
    display:block; }
.s-team .avatar.t1 { background:repeating-linear-gradient(135deg,#ED7A3D 0 14px,#F5B893 14px 28px); }
.s-team .avatar.t2 { background:repeating-linear-gradient(135deg,#14213D 0 14px,#1f2f54 14px 28px); }
.s-team .avatar.t3 { background:repeating-linear-gradient(135deg,#FFC83D 0 14px,#FFD76A 14px 28px); }
.s-team .avatar.t4 { background:repeating-linear-gradient(135deg,#C8A4E8 0 14px,#D7BBEE 14px 28px); }
.s-team .avatar.t5 { background:repeating-linear-gradient(135deg,#9BD9A5 0 14px,#B1E5B9 14px 28px); }
.s-team .avatar.t6 { background:repeating-linear-gradient(135deg,#F4A3A3 0 14px,#F7BCBC 14px 28px); }
.s-team .avatar.t7 { background:repeating-linear-gradient(135deg,#AED1E8 0 14px,#C5DCEE 14px 28px); }
.s-team .avatar .lab { position:absolute; top:8px; left:8px;
    font-family:'JetBrains Mono',monospace;
    font-size:9px; letter-spacing:.15em;
    padding:2px 6px; background:var(--ink); color:var(--cream);
    text-transform:uppercase; }
.s-team .pinfo { padding:14px 14px 16px; display:flex; flex-direction:column; gap:6px; }
.s-team .pname { font-family:'Archivo Black',sans-serif;
    font-size:16px; letter-spacing:-0.01em; line-height:1.1; }
.s-team .prole { font-family:'JetBrains Mono',monospace;
    font-size:10px; letter-spacing:.12em; text-transform:uppercase;
    color:var(--orange-deep); }
.s-team .pdesc { font-size:12.5px; line-height:1.4; color:var(--ink-mute); }
.s-team .pdesc b { color:var(--ink); font-weight:700; }
/* Inline email link inside each card. Layout-only here; visual style comes
   from the shared .email-link class. align-self keeps the highlighter band
   hugging the text instead of stretching the full card width. */
.s-team .pemail { margin:auto 14px 14px;
    align-self:flex-start;
    max-width:calc(100% - 28px);
    font-size:12px; }
/* On phone the cards go full-width, so the 4:3 avatar ends up too tall.
   16:9 is roughly 75% of that height. */
@media (max-width:600px) {
  .s-team .avatar { aspect-ratio:16/9; }
}


/* ============================================================
   SECTION: newsletter
   Sits between the team grid (paper) and the social-media feed
   (paper), so it uses the cream background to keep the page's
   paper → cream → paper alternation going into the footer.
   Layout mirrors .s-suggest: copy on the left, framed photo on
   the right, collapsing to a single column on mobile.
   ============================================================ */
.s-newsletter { background:var(--paper);
    padding:var(--section-pad-y) var(--section-pad-x);
    position:relative; overflow:hidden; }
.s-newsletter::before { content:""; position:absolute; top:-30px; left:-30px;
    width:180px;
    background:radial-gradient(#ED7A3D40 1.5px,transparent 2px);
    background-size:14px 14px;
    opacity:.5;
    pointer-events:none; }
.s-newsletter .grid { max-width:1160px; margin:0 auto;
    display:grid;
    /* Copy column is narrower than the photo so the newsletter
       mockup gets room to breathe at its native ~3:2 aspect. */
    grid-template-columns:minmax(0,1fr) minmax(0,1.15fr);
    gap:clamp(24px,4vw,56px);
    align-items:center;
    position:relative; z-index:1; }
.s-newsletter .head { display:flex; flex-direction:column; gap:16px;
    align-items:flex-start; }
.s-newsletter .head .btn { margin-top:4px; }
.s-newsletter .photo { position:relative;
    width:100%;
    aspect-ratio:1318/836; }
.s-newsletter .photo .newsletter-photo { position:absolute; inset:0;
    width:100%; height:100%;
    object-fit:cover; object-position:center;
    display:block; }
@media (max-width:960px) {
  .s-newsletter .grid { grid-template-columns:1fr; gap:28px; max-width:720px; }
  /* Flip visual order on tablet/phone so the newsletter mockup appears
     above the copy, even though it sits in the right column on
     desktop. Using `order` on grid items keeps DOM order
     (head → photo) intact for screen readers / SEO. */
  .s-newsletter .photo { order:1; aspect-ratio:1318/836; max-height:42vh; }
  .s-newsletter .head  { order:2; }
}
@media (max-width:600px) {
  .s-newsletter .photo { box-shadow:6px 6px 0 var(--orange); }
}


/* ============================================================
   SECTION: resources
   Paper (not cream) so it alternates against the cream newsletter
   section sitting directly above it.
   ============================================================ */
.s-resources { background:var(--cream);
    padding:var(--section-pad-y) var(--section-pad-x); }
.s-resources .head { max-width:1200px; margin:0 auto clamp(24px,3vw,36px); }
.s-resources .socials { max-width:1200px; margin:0 auto; }
.s-resources .feed { background:#fff; border:3px solid var(--ink-blue);
    overflow:hidden;
    display:flex; flex-direction:column; }
.s-resources .feed-head { padding:14px 18px;
    display:flex; align-items:center; justify-content:space-between;
    gap:10px 14px; flex-wrap:wrap;
    background:#fff; color:var(--ink-blue);
    border-bottom:2px solid var(--ink-blue); }
.s-resources .feed-head .name { font-family:'Archivo Black',sans-serif;
    font-size:18px; letter-spacing:-0.01em;
    display:flex; align-items:center; gap:8px; }
/* Fixed-height scroll viewport for the embedded feed. About half the
   natural unconstrained Elfsight height so the card stays compact, with
   internal vertical scrolling to reveal more posts. */
.s-resources .feed-body { padding:14px; background:#fff;
    height:760px; overflow-y:auto;
    -webkit-overflow-scrolling:touch; }
/* Elfsight injects its own widget styles; keep the container fluid so
   the feed fills the card and doesn't blow past the border. */
.s-resources .feed-body > div[class^="elfsight-app-"] { width:100%; }
@media (max-width:600px) {
  .s-resources .feed-body { height:570px; }
}


/* ============================================================
   SECTION: footer
   ============================================================ */
.s-footer { background:var(--orange);
    color:var(--ink);
    padding:var(--section-pad-y) var(--section-pad-x);
    position:relative; overflow:hidden; }
.s-footer::after { content:""; position:absolute; right:-40px; bottom:-40px;
    width:200px;
    background:radial-gradient(#1a141030 1px,transparent 1.5px);
    background-size:10px 10px; }
.s-footer .grid { max-width:1200px; margin:0 auto;
    display:grid;
    grid-template-columns:1.2fr 1fr 1fr;
    gap:clamp(20px,3vw,40px);
    position:relative; z-index:1; }
@media (max-width:600px) {
  .s-footer .grid { grid-template-columns:1fr; gap:24px; }
}
.s-footer .brand { display:flex; flex-direction:column; gap:12px; }
.s-footer .wordmark { font-family:'Archivo Black',sans-serif;
    font-size:clamp(28px,3.5vw,40px);
    line-height:.95; letter-spacing:-0.02em; }
.s-footer .tagline { font-size:14px; line-height:1.5; color:var(--ink-soft);
    max-width:36ch; }
.s-footer .col h4 { font-family:'JetBrains Mono',monospace;
    font-size:11px; letter-spacing:.2em; text-transform:uppercase;
    font-weight:700;
    margin:0 0 10px;
    padding-bottom:6px;
    border-bottom:2px solid var(--ink-blue); }
.s-footer .col ul { list-style:none; padding:0; margin:0;
    display:flex; flex-direction:column; gap:6px; }
.s-footer .col a { color:var(--ink-blue); text-decoration:none;
    font-weight:700; font-size:14px;
    display:inline-flex; align-items:center; gap:8px;
    padding:3px 0;
    border-bottom:2px solid transparent;
    transition:border-color .15s; }
.s-footer .col a:hover { border-bottom-color:var(--ink); }
.s-footer .col a::before { content:"→"; font-size:12px; color:#1a141080; }
.s-footer .foot { max-width:1200px; margin:clamp(24px,3vw,40px) auto 0;
    border-top:2px dashed #1a141060;
    padding-top:16px;
    display:flex; justify-content:space-between; align-items:center;
    gap:12px; flex-wrap:wrap;
    font-family:'JetBrains Mono',monospace;
    font-size:11px; letter-spacing:.12em;
    color:#1a141090;
    position:relative; z-index:1; }


/* ============================================================
   SECTION: bio
   Used by the Chinese landing page (/meet-scott-chinese/). The
   section runs full-bleed cream with a striped top accent (shared
   from the SHARED COMPONENTS block above) and a constrained
   reading-width prose column.
   ============================================================ */
.s-bio { background:var(--cream);
    padding:var(--section-pad-y) var(--section-pad-x);
    color:var(--ink);
    position:relative; overflow:hidden; }
.s-bio .prose { max-width:64ch; margin:0 auto;
    display:flex; flex-direction:column; gap:1.15em;
    font-size:clamp(16px,1.25vw,18px);
    line-height:1.9;
    color:var(--ink); }
/* Long-form bio body. Overrides the global `p` defaults so the
   reading column gets a slightly larger size, looser line-height,
   and full ink color — the global rule's max-width:54ch would
   otherwise cap the prose narrower than the .prose container. */
.s-bio .prose p { margin:0;
    font-size:inherit; line-height:inherit; color:inherit;
    max-width:none; }


/* ============================================================
   PAGE: Chinese landing (/meet-scott-chinese/)
   Type-stack swap and welcome-section overrides specific to the
   zh-Hant page. Kept in the shared stylesheet so the standalone
   page doesn't ship its own <style> block.
   ============================================================ */

/* Prefer Noto Sans TC for CJK glyphs; DM Sans stays the fallback for
   any Latin characters that sneak in (names, years, etc.). */
html[lang="zh-Hant"] body,
html[lang="zh-Hant"] .s-welcome .lede,
html[lang="zh-Hant"] .s-bio .prose {
  font-family:'DM Sans','Noto Sans TC',system-ui,sans-serif;
}

/* The .s-welcome H1 is designed around the short English phrase
   "showing up". For Chinese the characters sit too snugly inside the
   skewed em block, so loosen padding and bump line-height a touch. */
html[lang="zh-Hant"] .s-welcome .h1 { line-height:1.15; }
html[lang="zh-Hant"] .s-welcome .h1 em { padding:2px 18px; }

/* On the homepage the welcome section uses a tight bottom padding because
   it's paired with the countdowns below (the two read as one unit). On the
   Chinese page the next section is standalone prose, so restore the full
   --section-pad-y on the bottom to match the regular unrelated-sections
   spacing used everywhere else. */
html[lang="zh-Hant"] .s-welcome {
  padding:var(--section-pad-y) var(--section-pad-x);
}

/* On the Chinese page we want a stacked layout — H1 on top, then a wide
   hero photo below — instead of the side-by-side grid the main site uses
   for the welcome screen. Override .s-welcome's grid to a single column,
   center the text, and let the portrait grow to the full content width
   at a cinematic 21:9 crop. */
html[lang="zh-Hant"] .s-welcome .grid {
  grid-template-columns:1fr;
  gap:clamp(28px,4vw,44px);
  max-width:1160px;
}
html[lang="zh-Hant"] .s-welcome .intro { align-items:center; text-align:center; gap:14px; }
/* Restore centered alignment on the Chinese hero subtitle — the
   global `p` rule sets text-align:left which would otherwise
   override the centered .intro layout the Chinese page uses. */
html[lang="zh-Hant"] .s-welcome .lede { max-width:none; text-align:center; }
html[lang="zh-Hant"] .s-welcome .portrait {
  width:100%; max-width:none;
  aspect-ratio:21/9; min-height:0; max-height:none;
}
html[lang="zh-Hant"] .s-welcome .portrait .candidate { object-position:50% 22%; }
@media (max-width:960px) {
  html[lang="zh-Hant"] .s-welcome .portrait { aspect-ratio:16/9; }
}
@media (max-width:600px) {
  html[lang="zh-Hant"] .s-welcome .portrait { aspect-ratio:4/3; }
  html[lang="zh-Hant"] .s-welcome .portrait .candidate { object-position:72% 22%; }
}
