/* ============================================================================
   OSUPHOENIX STREAMWORKS — STYLES.CSS
   ============================================================================
   Aesthetic direction:
     "Broadcast control room meets engineering lab."
     Restrained, technical, sharp. Red as the active/alert color in an
     otherwise muted environment. Decorative corner brackets, monospaced
     instrument readouts, file-numbered section labels.

   File structure (in order):
     01. Design tokens (CSS variables) — change these to retheme everything
     02. Reset & base
     03. Typography
     04. Layout helpers
     05. Section label component (reused everywhere)
     06. Nav
     07. Hero
     08. Hero — dashboard readouts (the signature element)
     09. Buttons / CTAs
     10. Placeholder sections
     10b. About section
     10c. What I Build section
     10d. Tutorials section
     10e. Lightbox modal
     10f. Live & Community section
     10g. Values section
     10h. Join / tiers section
     10i. About page (separate page at /about/)
     10j. Affiliates & Partners page (separate page at /affiliates/)
     10k. Recommendations page (separate page at /recommendations/)
     10L. Portfolio page (separate page at /portfolio/)
     10M. Community page (separate page at /community/)
     11. Footer
     12. Animations
     13. Responsive (mobile / tablet)

   Reading order: top to bottom. Each section is preceded by a header
   comment so you can jump around.
   ============================================================================ */


/* ============================================================================
   01. DESIGN TOKENS
   ============================================================================
   These are the CSS custom properties (variables) that drive the entire site.
   Changing a value here updates everywhere it's referenced. This is the FIRST
   place to look when you want to tweak the look — colors, fonts, spacing.
   ============================================================================ */

:root {
  /* --- BACKGROUNDS ---
     The site uses three layers of dark: page bg, surface (cards), and
     elevated (hover/active states). Subtle differences add depth. */
  --bg-primary:   #0a0a0a;   /* page background — near-black */
  --bg-surface:   #141414;   /* card / panel surface */
  --bg-elevated:  #1c1c1c;   /* hover, active, elevated state */
  --bg-overlay:   rgba(10, 10, 10, 0.85);  /* sticky nav background */

  /* --- BRAND ACCENTS ---
     Red is the primary action color (CTAs, live indicators, highlights).
     Silver is the structural accent (borders, dividers, secondary text). */
  --red:          #e63946;   /* primary brand red */
  --red-bright:   #ff4757;   /* brighter red for highlights */
  --red-deep:     #b8232f;   /* deeper red, used sparingly */
  --red-tint:     rgba(230, 57, 70, 0.10);  /* subtle red wash overlay */
  --red-glow:     rgba(230, 57, 70, 0.35);  /* for soft glow effects */

  --silver:       #c8c8c8;   /* primary silver — section labels, accents */
  --silver-dim:   #8a8a8a;   /* dimmed silver — secondary labels */

  /* --- ALT ACCENT (cyan / teal) ---
     Used sparingly as a counterpoint to red. Sits roughly opposite red
     on the color wheel, so it reads as "diagnostic / instrument" rather
     than competing with the brand red. Currently used in the About
     section's animated backlight glow.

     To swap to a different alt color, change --cyan and --cyan-deep.
     Examples that would work in the same slot:
       Amber:  #e9b949 / #b88923
       Red-only: --red / --red-deep    (drop the alt entirely)
   */
  --cyan:         #7c39d4;
  --cyan-deep:    #581a8a;

  /* --- TEXT ---
     Three levels: primary (headlines), body (paragraphs),
     muted (captions/meta), dim (hints). */
  --text-primary: #f0f0f0;
  --text-body:    #c8c8c8;
  --text-muted:   #8a8a8a;
  --text-dim:     #555555;

  /* --- BORDERS ---
     Borders use rgba so they sit subtly over any background. */
  --border-subtle:  rgba(200, 200, 200, 0.08);
  --border-default: rgba(200, 200, 200, 0.15);
  --border-strong:  rgba(200, 200, 200, 0.30);
  --border-red:     rgba(230, 57, 70, 0.40);

  /* --- STATUS COLORS --- */
  --live:    #ff2e3f;   /* slightly hotter red for the live dot */
  --offline: #555555;

  /* --- TYPOGRAPHY ---
     Display: Rajdhani (geometric, technical)
     Body:    DM Sans (clean, neutral, very readable)
     Mono:    JetBrains Mono (the "instrument" font on dashboards) */
  --font-display: 'Rajdhani', system-ui, sans-serif;
  --font-body:    'DM Sans', system-ui, sans-serif;
  --font-mono:    'JetBrains Mono', 'Courier New', monospace;

  /* Type scale — based on a 1.25 ratio.
     Use these instead of arbitrary px values for visual consistency. */
  --text-xs:   0.75rem;    /* 12px */
  --text-sm:   0.875rem;   /* 14px */
  --text-base: 1rem;       /* 16px */
  --text-lg:   1.125rem;   /* 18px */
  --text-xl:   1.25rem;    /* 20px */
  --text-2xl:  1.5rem;     /* 24px */
  --text-3xl:  2rem;       /* 32px */
  --text-4xl:  2.75rem;    /* 44px */
  --text-5xl:  3.75rem;    /* 60px */
  --text-6xl:  5rem;       /* 80px */

  /* --- SPACING ---
     Multiples of 0.25rem (4px) keep the rhythm consistent. */
  --space-1:  0.25rem;
  --space-2:  0.5rem;
  --space-3:  0.75rem;
  --space-4:  1rem;
  --space-6:  1.5rem;
  --space-8:  2rem;
  --space-12: 3rem;
  --space-16: 4rem;
  --space-20: 5rem;
  --space-24: 6rem;
  --space-32: 8rem;

  /* --- LAYOUT --- */
  --container-max: 1280px;   /* maximum content width */
  --nav-height:    72px;     /* sticky nav height */

  /* Tool card thumbnail max height — caps the rendered thumb so cards
     don't tower in a 4-up row. Lower values = shorter, more cropped
     thumbnails. Higher values = taller cards. */
  --tool-thumb-max-height: 320px;

  /* --- MOTION ---
     Easing curves give animations character. Avoid linear except for
     constant motion (rotations, marquees). */
  --ease-out:    cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --duration-fast:   150ms;
  --duration-normal: 300ms;
  --duration-slow:   500ms;
}


/* ============================================================================
   02. RESET & BASE
   ============================================================================
   A minimal reset to normalize browser defaults without going overboard.
   Modern browsers handle most things consistently — we just need to flatten
   margins, fix box-sizing, and set a baseline.
   ============================================================================ */

*, *::before, *::after {
  box-sizing: border-box;
}

* {
  margin: 0;
  padding: 0;
}

html {
  scroll-behavior: smooth;
  /* Offset for sticky nav when jumping to anchors — without this,
     anchored sections get hidden under the nav. */
  scroll-padding-top: var(--nav-height);
}

body {
  background: var(--bg-primary);
  color: var(--text-body);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Prevent horizontal scroll from any decorative element bleeding off. */
  overflow-x: hidden;
}

a {
  color: inherit;
  text-decoration: none;
}

ul {
  list-style: none;
}

img {
  max-width: 100%;
  display: block;
}


/* ============================================================================
   03. TYPOGRAPHY
   ============================================================================ */

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.1;
  color: var(--text-primary);
  letter-spacing: -0.01em;
}

/* The accent-red span is used inside headlines to highlight one key phrase. */
.accent-red {
  color: var(--red);
}


/* ============================================================================
   04. LAYOUT HELPERS
   ============================================================================ */

.nav-container,
.hero-container,
.section-container,
.footer-container {
  max-width: var(--container-max);
  margin: 0 auto;
  padding-left: var(--space-8);
  padding-right: var(--space-8);
}


/* ============================================================================
   05. SECTION LABEL — used at the top of every section
   ============================================================================
   Format: [ 01 / Workshop ]
   Brackets and slashes are decorative — the actual content is the number
   and the name. Mono font keeps it feeling like a file or panel reference.
   ============================================================================ */

.section-label {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--silver-dim);
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-8);
}

.section-label-bracket {
  color: var(--red);
  font-weight: 500;
}

.section-label-num {
  color: var(--silver);
  font-weight: 500;
}

.section-label-divider {
  color: var(--text-dim);
}

.section-label-name {
  color: var(--silver-dim);
}


/* ============================================================================
   06. NAV
   ============================================================================
   Sticky nav. Starts transparent over the hero, gains a background and
   a subtle bottom border once the user scrolls past the hero.
   The "scrolled" class is added by main.js based on scroll position.
   ============================================================================ */

.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: var(--nav-height);
  z-index: 100;
  transition: background-color var(--duration-normal) var(--ease-out),
              border-color var(--duration-normal) var(--ease-out),
              backdrop-filter var(--duration-normal) var(--ease-out);
  border-bottom: 1px solid transparent;
}

.nav.scrolled {
  background: var(--bg-overlay);
  border-bottom-color: var(--border-subtle);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

.nav-container {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.nav-brand {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  color: var(--text-primary);
  letter-spacing: 0.04em;
}

/* NAV BRAND LOGO — small icon to the left of the brand text.
   File expected at: images/osuphoenix-logo.png
   If missing, the onerror handler in the HTML hides this element so
   the brand text shows alone (no broken image icon). */
.nav-brand-logo {
  height: 28px;
  width: auto;
  display: block;
  /* Subtle red glow on hover, matching the rest of the page's
     hover behavior. */
  transition: filter var(--duration-fast) var(--ease-out);
}

.nav-brand:hover .nav-brand-logo {
  filter: drop-shadow(0 0 4px var(--red-glow));
}

.brand-bracket  { color: var(--red); }
.brand-divider  { color: var(--text-dim); }
.brand-suffix   { color: var(--silver); }

.nav-menu {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  font-size: var(--text-sm);
}

.nav-menu a {
  color: var(--text-muted);
  font-weight: 500;
  letter-spacing: 0.02em;
  transition: color var(--duration-fast) var(--ease-out);
  position: relative;
}

.nav-menu a:hover {
  color: var(--text-primary);
}

/* The store CTA in the nav gets a small red border to distinguish it
   from regular nav links. */
.nav-cta {
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--border-red);
  border-radius: 2px;
  color: var(--red) !important;
  transition: all var(--duration-fast) var(--ease-out);
}

.nav-cta:hover {
  background: var(--red);
  color: var(--bg-primary) !important;
}


/* ─── NAV DROPDOWN ──────────────────────────────────────────────────────
   The "More ▾" trigger and its panel of secondary nav links.

   Behavior is fully click-driven (no hover-to-open) because hover
   doesn't translate to touch screens. JS in main.js toggles a
   `.show` class on .dropdown-content and flips `aria-expanded` on
   the button.

   Visually the panel uses the same dark surface and border vocabulary
   as everything else — small panel hanging from the button's bottom
   edge, links inside hover red like menu items.
   ─────────────────────────────────────────────────────────────────── */

/* The <li> wrapper. position: relative anchors the absolutely-positioned
   .dropdown-content panel to this element, NOT the page. */
.dropdown {
  position: relative;
}

/* The trigger button. Styled to match the surrounding .nav-menu links —
   same font, weight, color, hover behavior. The only visual cue that
   it's a dropdown trigger is the small ▾ arrow next to the label. */
.dropbtn {
  /* Reset default <button> styles so it blends into the nav link list */
  background: transparent;
  border: 0;
  padding: 0;
  margin: 0;
  cursor: pointer;
  /* Match the nav-menu link typography exactly */
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-weight: 500;
  letter-spacing: 0.05em;
  color: var(--text-body);
  /* Enough room for the arrow next to the label */
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  transition: color var(--duration-fast) var(--ease-out);
}

.dropbtn:hover,
.dropbtn[aria-expanded="true"] {
  color: var(--red);
}

/* The arrow rotates when the dropdown is open — a small affordance
   that signals "click me again to close." */
.dropbtn-arrow {
  display: inline-block;
  font-size: 0.85em;
  transition: transform var(--duration-fast) var(--ease-out);
}

.dropbtn[aria-expanded="true"] .dropbtn-arrow {
  transform: rotate(180deg);
}

/* The panel. Absolutely positioned so it floats below the button
   without affecting layout. Hidden by default; the .show class
   reveals it. */
.dropdown-content {
  position: absolute;
  top: calc(100% + var(--space-3));  /* small gap between button and panel */
  right: 0;                            /* aligns to right edge of button */
  min-width: 240px;
  display: flex;
  flex-direction: column;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  /* A small accent stripe at the top — same vocabulary as recs cards.
     Hints at the connection without copying it. */
  border-top: 2px solid var(--red);
  /* Subtle shadow to lift the panel off the page */
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  /* Hidden by default. JS adds .show to reveal. */
  opacity: 0;
  visibility: hidden;
  transform: translateY(-8px);
  transition: opacity   var(--duration-fast) var(--ease-out),
              transform var(--duration-fast) var(--ease-out),
              visibility 0s linear var(--duration-fast);
  /* Important: this needs to sit ABOVE the page content but BELOW
     anything modal. z-index: 100 keeps it above the hero etc. */
  z-index: 100;
}

.dropdown-content.show {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  /* Override the visibility-delay transition so showing is immediate */
  transition: opacity   var(--duration-fast) var(--ease-out),
              transform var(--duration-fast) var(--ease-out);
}

.dropdown-content a {
  display: block;
  padding: var(--space-3) var(--space-4);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-weight: 500;
  letter-spacing: 0.05em;
  color: var(--text-body);
  text-decoration: none;
  border-bottom: 1px solid var(--border-subtle);
  transition: all var(--duration-fast) var(--ease-out);
}

.dropdown-content a:last-child {
  border-bottom: 0;
}

.dropdown-content a:hover,
.dropdown-content a:focus {
  background: var(--bg-elevated);
  color: var(--red);
  /* Slight push to the right on hover — matches the cta-arrow → idiom */
  padding-left: calc(var(--space-4) + 4px);
  outline: none;
}


/* ─── NAV DROPDOWN — SOCIAL ICONS ──────────────────────────────────────────
   These rules MUST come after the .dropdown-content a rules above so they
   can override them. The !important flags are intentional — they reverse
   specific properties that .dropdown-content a sets incorrectly for icons:
     display: block      → we need inline-flex for a row layout
     padding             → icons need 0 padding, not text padding
     border-bottom       → no dividers between icons
     color               → must stay platform color, not turn red on hover
   ─────────────────────────────────────────────────────────────────────── */

/* Bump panel width — more links in the dropdown now */
.dropdown-content {
  min-width: 260px;
}

/* "Find me on" label above the icon row */
.social-icons-label {
  padding: var(--space-3) var(--space-4) var(--space-1);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-dim);
}

/* The flex row that holds all 8 icons */
.social-icons-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-2) var(--space-4) var(--space-4);
}

/* Each platform icon link — overrides .dropdown-content a */
.social-icon-link {
  display: inline-flex !important;   /* row layout, not stacked block */
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0 !important;             /* no text padding */
  color: var(--icon-color) !important;
  border-bottom: none !important;    /* no divider lines between icons */
  opacity: 0.45;                     /* dim = unlit neon tube */
  filter: none;
  background: transparent !important;
  border-radius: 4px;
  transition:
    opacity   var(--duration-fast) var(--ease-out),
    filter    var(--duration-fast) var(--ease-out),
    transform var(--duration-fast) var(--ease-out);
}

/* Hover — neon lights up. Higher specificity beats .dropdown-content a:hover */
.social-icons-row .social-icon-link:hover,
.social-icons-row .social-icon-link:focus-visible {
  opacity: 1;
  transform: scale(1.15);
  color: var(--icon-color) !important;  /* stay platform color, not red */
  background: transparent !important;
  padding-left: 0 !important;           /* block the left-shift from dropdown hover */
  /* Four-layer neon bloom: tight core → wide atmospheric diffusion */
  filter:
    drop-shadow(0 0  2px var(--icon-color))
    drop-shadow(0 0  6px var(--icon-color))
    drop-shadow(0 0 12px var(--icon-color))
    drop-shadow(0 0 20px var(--icon-color));
  outline: none;
}

.social-icons-row .social-icon-link:focus-visible {
  outline: 1px solid var(--icon-color);
  outline-offset: 2px;
}

/* ── LIVE STATE: platform icon glow ────────────────────────────────────────
   When the stream goes live, JS adds .platform-live to the specific
   streaming platform icons (Twitch, YouTube, Kick) in the nav dropdown.

   We reuse the exact same four-layer drop-shadow already used on hover —
   so the icons look "hovering" permanently while the stream is active.
   The opacity-pulse animation makes them breathe rather than static-glow,
   giving the eye a soft "something is happening" signal without being loud.

   Note: --icon-color is already set per-icon as an inline style in nav.html
   (e.g. style="--icon-color: #9146FF;" for Twitch), so we don't need to
   hardcode per-platform colors here — the variable does it automatically.
   ──────────────────────────────────────────────────────────────────────── */
.social-icon-link.platform-live {
  opacity: 1;                              /* fully lit, not the dim 0.45 default */
  filter:
    drop-shadow(0 0  2px var(--icon-color))
    drop-shadow(0 0  6px var(--icon-color))
    drop-shadow(0 0 12px var(--icon-color))
    drop-shadow(0 0 20px var(--icon-color));
  animation: platform-live-breathe 2.5s ease-in-out infinite;
}

/* Breathing pulse — opacity oscillates between fully lit and ~80%.
   Subtle enough to not distract, visible enough to signal "live." */
@keyframes platform-live-breathe {
  0%, 100% { opacity: 1.0; }
  50%       { opacity: 0.65; }
}

/* SVG inside each link */
.social-icon-svg {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  pointer-events: none; /* SVG shouldn't intercept the hover from the <a> */
}


/* ============================================================================
   07. HERO
   ============================================================================
   The hero takes over the top of the page. The hero-bg div behind the
   content is a CSS-only grid pattern that adds technical atmosphere
   without any image asset.
   ============================================================================ */

.hero {
  position: relative;
  min-height: 100vh;
  padding-top: calc(var(--nav-height) + var(--space-12));
  padding-bottom: var(--space-16);
  display: flex;
  align-items: center;
  overflow: hidden;
}

/* HERO BACKGROUND — pure CSS grid pattern with vignette.
   No image asset needed. Two layers stacked:
     1. A faint grid (linear gradients in two directions)
     2. A radial vignette darkening the corners
   Both are very subtle — they create atmosphere, not noise. */
.hero-bg {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    /* Grid: 1px lines every 60px, both directions */
    linear-gradient(to right,  rgba(200, 200, 200, 0.04) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(200, 200, 200, 0.04) 1px, transparent 1px),
    /* Subtle red glow from one corner */
    radial-gradient(ellipse at 80% 20%, var(--red-tint), transparent 60%);
  background-size: 60px 60px, 60px 60px, 100% 100%;
  /* Vignette via mask — fades grid out at edges so it doesn't compete
     with the content. */
  mask-image: radial-gradient(ellipse at center, black 50%, transparent 100%);
  -webkit-mask-image: radial-gradient(ellipse at center, black 50%, transparent 100%);
}

.hero-container {
  position: relative;
  z-index: 1;
  width: 100%;
}

/* HERO WATERMARK — Streamworks logo as a 15% opacity background mark.
   File expected at: images/streamworks-logo.png

   Position: anchored to the right side, slightly off-screen, large but
   restrained. Sits behind the content (z-index: 0 vs. content's z-index: 1).
   pointer-events: none so it never blocks clicks on whatever it overlaps.

   Tweak the values here to taste:
     - opacity:    higher = more visible logo
     - right:      more negative = bleeds further off-screen
     - width:      bigger = the watermark dominates more
     - background-image: swap the path to use a different file. */
.hero-watermark {
  position: absolute;
  top: 50%;
  right: -10%;
  transform: translateY(-50%);
  width: min(80vh, 720px);
  height: min(80vh, 720px);
  background-image: url('images/StreamWorks.png');
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  opacity: 0.15;
  pointer-events: none;
  z-index: 0;
}

/* HEADLINE
   Rajdhani at a large size with tight line-height. The letter-spacing
   is slightly negative to keep big type from feeling loose. */
.hero-headline {
  font-size: clamp(var(--text-3xl), 6vw, var(--text-6xl));
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--text-primary);
  max-width: 18ch;
  margin-bottom: var(--space-8);
}

/* SUBHEADLINE
   DM Sans, comfortable line-length (~60ch), muted color. */
.hero-subheadline {
  font-size: var(--text-lg);
  line-height: 1.6;
  color: var(--text-body);
  max-width: 60ch;
  margin-bottom: var(--space-12);
}

/* CTA GROUP — the "three doors" */
.hero-cta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-bottom: var(--space-20);
}


/* ============================================================================
   08. HERO — DASHBOARD READOUTS (the signature element)
   ============================================================================
   Four "instrument panel" cards in a row. Each has:
     • A monospace label (uppercase, small)
     • A big mono value (the readout)
     • A small meta line below
     • Decorative corner brackets in each corner
   On hover, the card lifts slightly and the corners turn red.
   ============================================================================ */

.dashboard {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-4);
  padding-top: var(--space-12);
  border-top: 1px solid var(--border-default);
}

.readout {
  position: relative;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  padding: var(--space-6) var(--space-4);
  transition: border-color var(--duration-fast) var(--ease-out),
              transform var(--duration-fast) var(--ease-out);
}

.readout:hover {
  border-color: var(--border-strong);
  transform: translateY(-2px);
}

.readout:hover .corner {
  background: var(--red);
}

/* CORNER BRACKETS — four small L-shaped marks, one in each corner.
   Drawn with two pseudo-element-style spans (or just plain spans with
   borders). We use background colors and two intersecting lines per
   corner for the L-shape effect. */
.readout-corners {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.corner {
  position: absolute;
  width: 8px;
  height: 8px;
  background: var(--silver-dim);
  transition: background var(--duration-fast) var(--ease-out);
  /* Mask that creates the L-shape (top-left orientation by default) */
  mask:
    linear-gradient(black, black) top    / 8px 1px no-repeat,
    linear-gradient(black, black) left   / 1px 8px no-repeat;
  -webkit-mask:
    linear-gradient(black, black) top    / 8px 1px no-repeat,
    linear-gradient(black, black) left   / 1px 8px no-repeat;
}

.corner.tl { top: -1px;    left: -1px; }
.corner.tr { top: -1px;    right: -1px; transform: rotate(90deg); }
.corner.br { bottom: -1px; right: -1px; transform: rotate(180deg); }
.corner.bl { bottom: -1px; left: -1px;  transform: rotate(270deg); }

.readout-label {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--silver-dim);
  margin-bottom: var(--space-3);
}

.readout-value {
  font-family: var(--font-mono);
  font-size: var(--text-3xl);
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.02em;
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.readout-suffix {
  font-size: var(--text-xl);
  color: var(--red);
}

.readout-meta {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-muted);
}

/* STATUS DOT — the live/offline indicator. Pulses when live. */
.status-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--offline);
  flex-shrink: 0;
}

.status-dot.live {
  background: var(--live);
  box-shadow: 0 0 0 0 var(--red-glow);
  animation: pulse-live 2s var(--ease-out) infinite;
}

/* ── LIVE STATE: stream status readout card glow ────────────────────────────
   When the stream is live, JS adds .is-live to the [data-readout="stream"]
   card. The whole tile gets a breathing red glow so it reads as "active"
   at a glance — not just the small dot.

   The corner brackets also shift to red to reinforce the live state using
   the existing .corner elements already in the HTML.

   Tuning: increase the box-shadow spread values for a more dramatic effect,
   or reduce opacity values for a subtler treatment.
   ──────────────────────────────────────────────────────────────────────── */
.readout[data-readout="stream"].is-live {
  box-shadow:
    0 0  6px rgba(230, 57, 70, 0.55),   /* tight inner red ring */
    0 0 18px rgba(230, 57, 70, 0.28),   /* main halo */
    0 0 36px rgba(230, 57, 70, 0.10);   /* soft ambient bleed */
  animation: readout-live-pulse 2.5s ease-in-out infinite;
}

/* Corner brackets light up red when live — they're already positioned,
   just need a color change. The transition on .corner handles the fade. */
.readout[data-readout="stream"].is-live .corner {
  background: var(--red);
}

/* Breathing glow on the card — synced close to the dot's pulse period
   but slightly slower so they don't feel mechanical. */
@keyframes readout-live-pulse {
  0%, 100% {
    box-shadow:
      0 0  6px rgba(230, 57, 70, 0.55),
      0 0 18px rgba(230, 57, 70, 0.28),
      0 0 36px rgba(230, 57, 70, 0.10);
  }
  50% {
    box-shadow:
      0 0 10px rgba(230, 57, 70, 0.85),
      0 0 28px rgba(230, 57, 70, 0.50),
      0 0 52px rgba(230, 57, 70, 0.18);
  }
}


/* ============================================================================
   09. BUTTONS / CTAs
   ============================================================================ */

.cta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-6);
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 500;
  letter-spacing: 0.04em;
  border-radius: 2px;
  transition: all var(--duration-fast) var(--ease-out);
  border: 1px solid transparent;
}

.cta-arrow {
  transition: transform var(--duration-fast) var(--ease-out);
}

.cta:hover .cta-arrow {
  transform: translateX(4px);
}

/* Primary CTA — solid red, fills with red on idle, shifts on hover. */
.cta-primary {
  background: var(--red);
  color: var(--bg-primary);
  border-color: var(--red);
}

.cta-primary:hover {
  background: var(--red-bright);
  border-color: var(--red-bright);
}

/* Secondary CTA — outlined silver, gains red border on hover. */
.cta-secondary {
  background: transparent;
  color: var(--text-primary);
  border-color: var(--border-strong);
}

.cta-secondary:hover {
  border-color: var(--red);
  color: var(--red);
}

.cta-streamerbot {
  background:   transparent;
  color:        var(--text-primary);
  border-color: rgba(162, 87, 237, 0.6); /* static purple border */

  animation: glow-streamerbot 3s ease-in-out infinite;

  transition: border-color var(--duration-fast) var(--ease-out),
              color         var(--duration-fast) var(--ease-out);
}

.cta-streamerbot:hover {
  border-color: rgba(7, 158, 183, 0.9); /* border shifts to cyan on hover */
  color:        rgba(7, 158, 183, 1);
}

@keyframes glow-streamerbot {
  0% {
    box-shadow:
      0 0  4px rgba(162, 87, 237, 0.7),  /* purple inner */
      0 0 14px rgba(162, 87, 237, 0.4),  /* purple halo */
      0 0 28px rgba(162, 87, 237, 0.15); /* purple bleed */
  }
  50% {
    box-shadow:
      0 0  4px rgba(7, 158, 183, 0.7),   /* cyan inner */
      0 0 14px rgba(7, 158, 183, 0.4),   /* cyan halo */
      0 0 28px rgba(7, 158, 183, 0.15);  /* cyan bleed */
  }
  100% {
    box-shadow:
      0 0  4px rgba(162, 87, 237, 0.7),  /* back to purple — loops cleanly */
      0 0 14px rgba(162, 87, 237, 0.4),
      0 0 28px rgba(162, 87, 237, 0.15);
  }
}

/* ============================================================================
   10. PLACEHOLDER SECTIONS
   ============================================================================
   These are the sections we haven't fully designed yet. Each has the
   section label, a working title, and a "next iteration" note. They share
   a consistent base so the site reads as one cohesive design even before
   each section is fully built out.
   ============================================================================ */

.section {
  padding: var(--space-24) 0;
  border-top: 1px solid var(--border-subtle);
}

.section-placeholder {
  min-height: 50vh;
}

.section-title {
  font-size: var(--text-3xl);
  margin-bottom: var(--space-4);
  color: var(--text-primary);
}

.placeholder-note {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--text-muted);
  max-width: 70ch;
  padding: var(--space-4) var(--space-6);
  background: var(--bg-surface);
  border-left: 2px solid var(--red);
}


/* ============================================================================
   10b. ABOUT SECTION
   ============================================================================
   Two-column offset grid. The right column is shifted up via negative
   margin so the photo sits visually higher than the text headline,
   creating intentional asymmetry. The pull quote breaks the text column
   on desktop and overlaps slightly into the photo column gutter.

   Mobile collapses to a single column with the photo on top — that order
   is set by `order` properties so we don't have to rewrite the HTML.
   ============================================================================ */

/* Need positioning context for the absolute-positioned watermark. */
.about {
  position: relative;
  overflow: hidden;
}

/* ABOUT WATERMARK — OSUPhoenix logo as a 15% opacity background mark.
   Mirror of the hero watermark, but anchored on the LEFT side and
   slightly offset off-screen. Opposite-side placement creates visual
   rhythm as visitors scroll between sections.

   File expected at: images/osuphoenix-logo.png
   Tweak values here:
     - opacity:  higher = more visible logo
     - left:     more negative = bleeds further off-screen
     - width:    bigger = the watermark dominates more
     - background-image: swap the path to use a different file. */
.about-watermark {
  position: absolute;
  top: 50%;
  left: -10%;
  transform: translateY(-50%);
  width: min(70vh, 600px);
  height: min(70vh, 600px);
  background-image: url('images/osuphoenix-logo.png');
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  opacity: 0.15;
  pointer-events: none;
  z-index: 0;
}

/* The about content needs to stack above the watermark. */
.about .section-container {
  position: relative;
  z-index: 1;
}

.about-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-16);
  align-items: start;
  position: relative;
}

.about-text {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

.about-headline {
  font-size: clamp(var(--text-3xl), 4vw, var(--text-5xl));
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--text-primary);
  margin-bottom: var(--space-4);
}

.about-text p {
  font-size: var(--text-base);
  line-height: 1.7;
  color: var(--text-body);
  max-width: 60ch;
}

.about-text strong {
  color: var(--text-primary);
  font-weight: 700;
}

.about-text em {
  color: var(--silver);
  font-style: normal;
  letter-spacing: 0.02em;
}

/* PULL QUOTE — the asymmetry moment.
   Larger type, set off with a left border in red, hangs slightly into
   the photo column's gutter via negative right margin. */
.about-pullquote {
  position: relative;
  margin: var(--space-6) 0;
  padding: var(--space-4) var(--space-6);
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: var(--text-primary);
  border-left: 3px solid var(--red);
  background: linear-gradient(
    to right,
    var(--red-tint),
    transparent 70%
  );
  /* Bleed slightly to the right on desktop — into the gutter, not the
     photo. This is the grid-breaking move. */
  margin-right: calc(-1 * var(--space-12));
}

.pullquote-mark {
  font-family: var(--font-display);
  font-size: var(--text-4xl);
  color: var(--red);
  line-height: 0;
  margin-right: var(--space-2);
  vertical-align: -0.2em;
}

.about-cta {
  align-self: flex-start;
  margin-top: var(--space-2);
}


/* PHOTO COLUMN
   The whole column is offset upward with a negative top margin to break
   the symmetric "text and photo start at the same y" pattern.
   This is what gives the section its visual personality. */
.about-photo-col {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  margin-top: var(--space-12);
}

/* PHOTO WRAPPER
   This wrapper exists so the animated backlight glow can extend past
   the photo's frame without being clipped. The .about-photo itself
   has overflow:hidden (to crop the portrait), which would cut off any
   glow attached directly to it. The wrapper has no overflow rule, so
   its ::before pseudo-element can spill outside the photo's edges. */
.about-photo-wrap {
  position: relative;
  /* `isolation: isolate` creates a new stacking context here, so the
     ::before pseudo-element with negative z-index sits behind the photo
     but above the page background (instead of going behind the page). */
  isolation: isolate;
}

/* ANIMATED BACKLIGHT GLOW
   Pure-CSS port of the SCSS mixin technique: a heavily-blurred gradient
   sits behind the photo, with `background-position` animated from one
   side to the other, creating the impression of slowly shifting
   atmospheric color. The gradient cycles between brand red and the alt
   cyan accent, giving the section a touch of warmth and movement without
   competing with the photo itself.

   Tuning notes (all on this rule):
     • inset: -10%        → glow extends 10% past the wrapper edges
     • filter: blur(56px) → very soft halo, not a sharp outline
     • opacity: 0.50      → subtle, not loud (raise for more presence)
     • z-index: -1        → sits behind the photo (inside the wrapper's
                              stacking context, thanks to `isolation`)
     • animation: 20s     → slow ambient cycle (faster = more distracting)
*/
.about-photo-wrap::before {
  content: "";
  position: absolute;
  inset: -10%;
  z-index: -1;
  background: linear-gradient(
    270deg,
    var(--red),
    var(--cyan),
    var(--red-deep),
    var(--cyan-deep),
    var(--red)
  );
  background-size: 400% 400%;
  filter: blur(56px);
  opacity: 0.50;
  animation: about-glow 20s linear infinite;
  pointer-events: none;
}

/* Slightly intensify the glow on hover. */
.about-photo-wrap:hover::before {
  opacity: 0.75;
  transition: opacity var(--duration-slow) var(--ease-out);
}

.about-photo {
  position: relative;
  aspect-ratio: 4 / 5;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  overflow: hidden;
  transition: border-color var(--duration-normal) var(--ease-out);
}

.about-photo:hover {
  border-color: var(--border-strong);
}

.about-photo:hover .corner {
  background: var(--red);
}

.about-photo-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  /* Subtle desaturation that gradually returns to full color on hover.
     Reads as "professional portrait" rather than "filtered selfie". */
  filter: saturate(0.85);
  transition: filter var(--duration-slow) var(--ease-out);
}

.about-photo:hover .about-photo-img {
  filter: saturate(1);
}

/* PHOTO FALLBACK — only shown if the image file is missing.
   Hidden by default; the <img> tag's onerror handler reveals it when
   the image fails to load. */
.about-photo-fallback {
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  width: 100%;
  height: 100%;
  background:
    repeating-linear-gradient(
      45deg,
      var(--bg-surface),
      var(--bg-surface) 10px,
      var(--bg-elevated) 10px,
      var(--bg-elevated) 20px
    );
  font-family: var(--font-mono);
  text-align: center;
  padding: var(--space-6);
}

.fallback-label {
  font-size: var(--text-sm);
  font-weight: 700;
  letter-spacing: 0.2em;
  color: var(--silver);
}

.fallback-meta {
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.fallback-hint {
  font-size: var(--text-xs);
  color: var(--text-dim);
  font-style: italic;
}


/* CREDENTIAL READOUTS — three smaller dashboard-style cards below the
   photo. Use the same .readout class as the hero dashboard for visual
   consistency, but with .readout-value-sm for less-overwhelming type
   on these denser cards. */
.about-credentials {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3);
}

.readout-value-sm {
  font-family: var(--font-mono);
  font-size: var(--text-base);
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.01em;
  margin-bottom: var(--space-2);
}


/* ============================================================================
   10c. WHAT I BUILD SECTION
   ============================================================================
   Two stacked sub-blocks: services (top) and tools (bottom).
   Both use 2×2 grids on desktop. Each block has an eyebrow label that
   ties back to the [section-label] aesthetic but at smaller scale.
   ============================================================================ */

.build-title {
  font-size: clamp(var(--text-3xl), 4vw, var(--text-5xl));
  margin-bottom: var(--space-4);
  max-width: 22ch;
}

.build-intro {
  font-size: var(--text-lg);
  color: var(--text-body);
  max-width: 60ch;
  margin-bottom: var(--space-16);
}

/* Eyebrow labels — smaller siblings of the [section-label] component.
   Used at the top of each sub-block (Services, From the workshop). */
.services-eyebrow,
.tools-eyebrow {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--silver-dim);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border-subtle);
  margin-bottom: var(--space-8);
  position: relative;
}

/* Small red tick before each eyebrow — visual rhyme with section labels. */
.services-eyebrow::before,
.tools-eyebrow::before {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  background: var(--red);
  margin-right: var(--space-3);
  vertical-align: 1px;
}

/* ----- SERVICES ----- */

.services-block {
  margin-bottom: var(--space-20);
}

.services-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}

.service-card {
  position: relative;
  padding: var(--space-8) var(--space-6);
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  transition: border-color var(--duration-normal) var(--ease-out),
              transform   var(--duration-fast) var(--ease-out);
}

.service-card:hover {
  border-color: var(--border-strong);
  transform: translateY(-2px);
}

/* Service card corners turn red on hover, matching the pattern used on
   dashboard readouts, About credentials, and the photo frame. Visual
   consistency across all corner-bracketed elements on the page. */
.service-card:hover .corner {
  background: var(--red);
}

/* Big numeral in the corner — establishes a count and adds visual weight
   without needing an icon for each service. */
.service-num {
  position: absolute;
  top: var(--space-4);
  right: var(--space-6);
  font-family: var(--font-mono);
  font-size: var(--text-3xl);
  font-weight: 700;
  color: var(--text-dim);
  letter-spacing: -0.02em;
  transition: color var(--duration-normal) var(--ease-out);
}

.service-card:hover .service-num {
  color: var(--red);
}

.service-name {
  font-size: var(--text-2xl);
  margin-bottom: var(--space-3);
  padding-right: var(--space-12);  /* leave room for the numeral */
  color: var(--text-primary);
}

.service-desc {
  font-size: var(--text-base);
  line-height: 1.6;
  color: var(--text-body);
  max-width: 50ch;
}

.services-cta {
  margin-top: var(--space-2);
}


/* ----- TOOLS ----- */

.tools-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-bottom: var(--space-8);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border-subtle);
}

.tools-header .tools-eyebrow {
  margin-bottom: 0;
  border-bottom: none;
  padding-bottom: 0;
}

.tools-meta {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-muted);
  letter-spacing: 0.05em;
}

#tools-count {
  color: var(--silver);
  font-weight: 700;
}

.tools-grid {
  display: grid;
  /* 4 cards in a single row on desktop. The 2×2 alternative looked tall
     and overweighted; one row keeps the section flowing into [04]. */
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-4);
  margin-bottom: var(--space-6);
  /* min-height keeps the layout stable while cards are being injected. */
  min-height: 200px;
}

.tools-fallback {
  grid-column: 1 / -1;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--text-muted);
  padding: var(--space-8);
  text-align: center;
}

/* TOOL CARD
   Built by JS. Two variants depending on whether `image` is provided:
     • With image  — thumbnail on top (3:2), info below
     • No image    — name takes the whole top half in display type */
.tool-card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  text-decoration: none;
  transition: border-color var(--duration-normal) var(--ease-out),
              transform   var(--duration-fast) var(--ease-out);
  color: inherit;
  overflow: hidden;
}

.tool-card:hover {
  border-color: var(--red);
  transform: translateY(-2px);
}

.tool-card:hover .corner {
  background: var(--red);
}

.tool-card:hover .tool-arrow {
  transform: translateX(4px);
  color: var(--red);
}

/* THUMBNAIL — only present on cards with an image.
   We use a max-aspect-ratio approach instead of a fixed aspect-ratio so
   the cards stay reasonable height in a 4-up row. The image is your
   original 900×1200 portrait (no cropping needed in your file), but
   `object-fit: cover` lets the browser show the center portion if the
   container's resolved aspect is wider than 3:4. The actual rendered
   ratio depends on card width — taller cards on narrow viewports, more
   cropped on wide viewports.

   The aspect-ratio is set to 3:4 with a max-height cap so very wide
   viewports don't produce towering cards. Tweak --tool-thumb-max-height
   in the design tokens to taste. */
.tool-thumb {
  position: relative;
  aspect-ratio: 3 / 4;
  max-height: var(--tool-thumb-max-height);
  background: var(--bg-elevated);
  overflow: hidden;
  border-bottom: 1px solid var(--border-default);
}

.tool-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(0.9);
  transition: filter var(--duration-slow) var(--ease-out);
}

.tool-card:hover .tool-thumb img {
  filter: saturate(1);
}

/* TYPOGRAPHIC HEADER — used when no thumbnail is provided.
   Mirrors the .tool-thumb dimensions so cards line up at the same
   height regardless of which variant they use. */
.tool-typeheader {
  position: relative;
  aspect-ratio: 3 / 4;
  max-height: var(--tool-thumb-max-height);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6);
  /* Faint grid pattern echoes the hero background — keeps the
     image-less cards from looking flat. */
  background:
    linear-gradient(to right,  rgba(200, 200, 200, 0.04) 1px, transparent 1px) 0 0 / 24px 24px,
    linear-gradient(to bottom, rgba(200, 200, 200, 0.04) 1px, transparent 1px) 0 0 / 24px 24px,
    var(--bg-surface);
  border-bottom: 1px solid var(--border-default);
  text-align: center;
  overflow: hidden;
}

.tool-typeheader-name {
  font-family: var(--font-display);
  font-size: clamp(var(--text-xl), 2.5vw, var(--text-3xl));
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--silver);
  transition: color var(--duration-normal) var(--ease-out);
}

.tool-card:hover .tool-typeheader-name {
  color: var(--text-primary);
}

/* BADGE — top-right corner, free or paid marker. */
.tool-badge {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  padding: var(--space-1) var(--space-2);
  background: var(--bg-overlay);
  border: 1px solid var(--border-default);
  z-index: 2;
}

.tool-badge.free {
  color: var(--red);
  border-color: var(--border-red);
}

.tool-badge.paid {
  color: var(--silver);
}

/* CARD BODY — tool name and description below the visual. */
.tool-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4);
  flex: 1;
}

.tool-name {
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--text-primary);
  margin: 0;
}

.tool-desc {
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--text-body);
  flex: 1;
}

.tool-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--silver);
  transition: color var(--duration-fast) var(--ease-out);
}

.tool-arrow {
  transition: transform var(--duration-fast) var(--ease-out),
              color     var(--duration-fast) var(--ease-out);
  color: var(--silver-dim);
}

.tools-cta {
  margin-top: var(--space-4);
}


/* ============================================================================
   10d. TUTORIALS SECTION
   ============================================================================
   Four-card row matching the hero/tools-section visual rhythm:
     • Three "tutorial cards" (auto-fetched playlist data)
     • One "channel card" (static, service-style with corner brackets)

   Each card is a clickable element that triggers the lightbox (10e).
   Cards have a loading state (skeleton shimmer) and a loaded state.
   ============================================================================ */

.tutorials-title {
  font-size: clamp(var(--text-3xl), 4vw, var(--text-5xl));
  margin-bottom: var(--space-4);
  max-width: 24ch;
}

.tutorials-intro {
  font-size: var(--text-lg);
  color: var(--text-body);
  max-width: 60ch;
  margin-bottom: var(--space-12);
}

.tutorials-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-4);
}

/* TUTORIAL CARD — base styles shared by playlist cards and channel card */
.tutorial-card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  text-decoration: none;
  color: inherit;
  cursor: pointer;
  overflow: hidden;
  transition: border-color var(--duration-normal) var(--ease-out),
              transform   var(--duration-fast) var(--ease-out);
}

.tutorial-card:hover {
  border-color: var(--red);
  transform: translateY(-2px);
}

/* Eyebrow — small monospace label at top of card */
.tutorial-eyebrow {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.15em;
  color: var(--silver-dim);
  padding: var(--space-3) var(--space-4) 0;
  transition: color var(--duration-fast) var(--ease-out);
}

.tutorial-card:hover .tutorial-eyebrow {
  color: var(--red);
}

/* THUMBNAIL — 16:9 to match YouTube's aspect ratio.
   Image fills via object-fit: cover. The play overlay sits on top. */
.tutorial-thumb {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--bg-elevated);
  margin: var(--space-3) var(--space-4);
  overflow: hidden;
  border: 1px solid var(--border-default);
}

.tutorial-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(0.85);
  transition: filter var(--duration-slow) var(--ease-out),
              transform var(--duration-slow) var(--ease-out);
}

.tutorial-card:hover .tutorial-thumb img {
  filter: saturate(1);
  transform: scale(1.03);
}

/* Play-button overlay on the thumbnail. CSS-drawn triangle inside a
   circle. Appears centered, becomes more prominent on hover. */
.tutorial-thumb::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 56px;
  height: 56px;
  transform: translate(-50%, -50%);
  background: rgba(10, 10, 10, 0.75);
  border: 2px solid var(--silver);
  border-radius: 50%;
  transition: background var(--duration-fast) var(--ease-out),
              border-color var(--duration-fast) var(--ease-out);
  pointer-events: none;
}

/* The triangle inside the circle — drawn with an inline SVG-like glyph
   isn't necessary; we use a CSS triangle via clip-path. */
.tutorial-thumb::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  transform: translate(-35%, -50%);
  z-index: 1;
  border-style: solid;
  border-width: 10px 0 10px 16px;
  border-color: transparent transparent transparent var(--silver);
  transition: border-left-color var(--duration-fast) var(--ease-out);
  pointer-events: none;
}

.tutorial-card:hover .tutorial-thumb::after {
  background: var(--red);
  border-color: var(--red);
}

.tutorial-card:hover .tutorial-thumb::before {
  border-left-color: var(--bg-primary);
}

/* SKELETON — loading state. A subtle shimmer fills the thumb area
   while the fetch is in flight. */
.tutorial-skeleton {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    90deg,
    var(--bg-surface) 0%,
    var(--bg-elevated) 50%,
    var(--bg-surface) 100%
  );
  background-size: 200% 100%;
  animation: tutorial-shimmer 1.5s ease-in-out infinite;
}

/* Hide the play overlay during loading — there's nothing to play yet. */
.tutorial-card.loading .tutorial-thumb::after,
.tutorial-card.loading .tutorial-thumb::before {
  display: none;
}

/* Body — title and watch link. */
.tutorial-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4) var(--space-4);
  flex: 1;
}

.tutorial-title {
  font-size: var(--text-base);
  font-weight: 600;
  line-height: 1.3;
  color: var(--text-primary);
  margin: 0;
  /* Limit to 2 lines max; ellipsis if longer.
     -webkit-line-clamp is widely supported and graceful when not. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.tutorial-card.loading .tutorial-title {
  color: var(--text-muted);
  font-weight: 500;
}

.tutorial-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: auto;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--silver);
}

.tutorial-play {
  color: var(--red);
  font-size: var(--text-base);
  line-height: 1;
}


/* CHANNEL CARD — service-card style, no thumbnail, big YouTube glyph */
.channel-card {
  background: var(--bg-surface);
  padding: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  justify-content: space-between;
}

.channel-card .tutorial-eyebrow {
  padding: 0;
}

.channel-card-icon {
  color: var(--red);
  transition: transform var(--duration-normal) var(--ease-out);
}

.channel-card:hover .channel-card-icon {
  transform: scale(1.05);
}

.channel-card:hover .corner {
  background: var(--red);
}

.channel-card-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.channel-card-title {
  font-size: var(--text-2xl);
  font-weight: 600;
  color: var(--text-primary);
  line-height: 1.2;
  margin: 0;
}

.channel-card-desc {
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--text-body);
  margin: 0;
}


/* ============================================================================
   10e. LIGHTBOX MODAL — for inline video playback
   ============================================================================
   Fullscreen overlay with a centered iframe. Hidden by default;
   `aria-hidden="false"` (set by JS) reveals it. Backdrop is dark
   semi-transparent; clicking the backdrop closes the modal.
   ============================================================================ */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: none;
  align-items: center;
  justify-content: center;
  padding: var(--space-8);
  background: rgba(10, 10, 10, 0.92);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.lightbox[aria-hidden="false"] {
  display: flex;
  animation: lightbox-fade var(--duration-normal) var(--ease-out);
}

.lightbox-frame {
  position: relative;
  width: 100%;
  max-width: 1200px;
  aspect-ratio: 16 / 9;
  border: 1px solid var(--border-strong);
  background: #000;
  box-shadow: 0 0 0 1px var(--red), 0 30px 80px rgba(0, 0, 0, 0.6);
}

.lightbox-frame iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

.lightbox-close {
  position: absolute;
  top: var(--space-6);
  right: var(--space-6);
  width: 44px;
  height: 44px;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  color: var(--silver);
  font-size: 28px;
  font-family: var(--font-display);
  line-height: 1;
  cursor: pointer;
  z-index: 1001;
  transition: all var(--duration-fast) var(--ease-out);
}

.lightbox-close:hover {
  background: var(--red);
  border-color: var(--red);
  color: var(--bg-primary);
}


/* ============================================================================
   10f. LIVE & COMMUNITY SECTION
   ============================================================================
   Three rows:
     • Live panel (info + stage with Twitch embed or offline state)
     • Community grid (Winnable Wednesday card + Thee Network card)
     • Standards banner (the One Rule, full width)

   Visual approach: clean cards with strong logo imagery doing the heavy
   lifting, restrained surrounding decoration. The corner brackets and
   eyebrow ticks tie back to the rest of the page's vocabulary.
   ============================================================================ */

.live-title {
  font-size: clamp(var(--text-3xl), 4vw, var(--text-5xl));
  margin-bottom: var(--space-12);
  max-width: 24ch;
}

/* ----- ROW 1 — LIVE PANEL ----- */

.live-panel {
  display: grid;
  grid-template-columns: 1fr 1.6fr;  /* info column narrower than stage */
  gap: var(--space-4);
  margin-bottom: var(--space-12);
  min-height: 320px;
}

.live-panel-info {
  position: relative;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  padding: var(--space-8) var(--space-6);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--space-4);
  transition: border-color var(--duration-normal) var(--ease-out);
}

/* When the stream is live, the info panel border becomes red to draw
   the eye. The .live state is set on the parent .live-panel by main.js. */
.live-panel[data-state="live"] .live-panel-info {
  border-color: var(--border-red);
}

.live-panel[data-state="live"] .live-panel-info .corner {
  background: var(--red);
}

.live-status {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.2em;
  color: var(--silver-dim);
  text-transform: uppercase;
}

.live-panel[data-state="live"] .live-status {
  color: var(--red);
}

.live-status-text {
  /* Reserve a min width so the layout doesn't shift between OFFLINE and LIVE */
  min-width: 60px;
}

.live-channel {
  font-family: var(--font-display);
  font-size: clamp(var(--text-xl), 2.5vw, var(--text-3xl));
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.01em;
  margin: 0;
  word-break: break-word;
}

.live-meta {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--text-muted);
  margin: 0;
}

#live-panel-countdown {
  color: var(--silver);
  font-weight: 700;
}

.live-cta {
  align-self: flex-start;
  margin-top: var(--space-2);
}

/* The stage — holds either the Twitch embed or the offline state. */
.live-panel-stage {
  position: relative;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  overflow: hidden;
  min-height: 320px;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* OFFLINE state — clean, intentional, not "broken". */
.live-panel-offline {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-8);
  text-align: center;
  background:
    /* subtle grid like the hero — ties this offline state to the rest of
       the page's atmosphere instead of looking like a placeholder */
    linear-gradient(to right,  rgba(200, 200, 200, 0.04) 1px, transparent 1px) 0 0 / 32px 32px,
    linear-gradient(to bottom, rgba(200, 200, 200, 0.04) 1px, transparent 1px) 0 0 / 32px 32px,
    var(--bg-surface);
  width: 100%;
  height: 100%;
  justify-content: center;
}

/* The "off-air" mark — three vertical bars suggesting an audio meter at
   rest. Pure CSS, no image. */
.offline-mark {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  height: 40px;
  margin-bottom: var(--space-3);
  opacity: 0.4;
}

.offline-bar {
  display: block;
  width: 6px;
  background: var(--silver-dim);
}

.offline-bar:nth-child(1) { height: 30%; }
.offline-bar:nth-child(2) { height: 60%; }
.offline-bar:nth-child(3) { height: 45%; }

.offline-text {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 700;
  color: var(--text-body);
  letter-spacing: -0.01em;
}

.offline-sub {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-muted);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* The embed wrapper — fills the stage. iframe inside is responsive. */
.live-panel-embed {
  width: 100%;
  height: 100%;
  position: relative;
}

.live-panel-embed iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}


/* ----- ROW 2 — COMMUNITY GRID ----- */

.community-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
  margin-bottom: var(--space-12);
}

.community-card {
  position: relative;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  padding: var(--space-8) var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  transition: border-color var(--duration-normal) var(--ease-out),
              transform   var(--duration-fast) var(--ease-out);
}

.community-card:hover {
  border-color: var(--border-strong);
  transform: translateY(-2px);
}

.community-card:hover .corner {
  background: var(--red);
}

/* Eyebrow with red tick — same vocabulary as the rest of the page. */
.community-card-eyebrow {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.2em;
  color: var(--silver-dim);
  text-transform: uppercase;
}

.eyebrow-tick {
  display: inline-block;
  width: 8px;
  height: 8px;
  background: var(--red);
  flex-shrink: 0;
}

/* Tiny "21+" badge for Winnable Wednesday — sits inline in the eyebrow,
   confident but not warning-label-loud. */
.ww-age-badge {
  margin-left: auto;
  padding: 2px 8px;
  background: var(--red);
  color: var(--bg-primary);
  font-size: var(--text-xs);
  letter-spacing: 0.05em;
}

/* The badge/logo containers — center the image with breathing room. */
.ww-badge,
.network-badge {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  /* Constrain badge height so cards stay in proportion to each other */
  min-height: 200px;
}

.ww-badge img,
.network-badge img {
  max-width: 100%;
  max-height: 200px;
  width: auto;
  height: auto;
  display: block;
  /* A subtle saturation that comes alive on hover — same trick used on
     the about photo and tool thumbnails. */
  filter: saturate(0.9);
  transition: filter var(--duration-slow) var(--ease-out),
              transform var(--duration-slow) var(--ease-out);
}

.community-card:hover .ww-badge img,
.community-card:hover .network-badge img {
  filter: saturate(1);
  transform: scale(1.04);
}

.community-card-title {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.01em;
  margin: 0;
}

.community-card-desc {
  font-size: var(--text-base);
  line-height: 1.6;
  color: var(--text-body);
  margin: 0;
}

.community-card-note {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  line-height: 1.5;
  color: var(--text-muted);
  letter-spacing: 0.04em;
  padding: var(--space-3);
  background: var(--bg-elevated);
  border-left: 2px solid var(--silver-dim);
  margin: 0;
}

.community-cta {
  align-self: flex-start;
  margin-top: var(--space-2);
}


/* ----- ROW 3 — STANDARDS BANNER ----- */

.standards-banner {
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-left: 4px solid var(--red);
  padding: var(--space-8) var(--space-12);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.standards-eyebrow {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.25em;
  color: var(--silver-dim);
  text-transform: uppercase;
}

.standards-headline {
  font-family: var(--font-display);
  font-size: clamp(var(--text-2xl), 3vw, var(--text-4xl));
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.1;
  color: var(--text-primary);
  margin: 0;
}

.standards-detail {
  font-size: var(--text-base);
  line-height: 1.7;
  color: var(--text-body);
  max-width: 75ch;
  margin: 0;
}


/* ============================================================================
   10g. VALUES SECTION
   ============================================================================
   Mental health + community standards. Restrained typography is the
   design — no animations, no imagery, plenty of breathing room. The
   content carries the weight here, not the visual treatment.

   Two subsections share the same .values-block container so they have
   consistent rhythm. Each gets an eyebrow label, prose, and (for mental
   health) a small resources grid below.
   ============================================================================ */

.values-title {
  font-size: clamp(var(--text-3xl), 4vw, var(--text-5xl));
  margin-bottom: var(--space-12);
  max-width: 24ch;
}

.values-block {
  margin-bottom: var(--space-16);
  /* Generous max-width keeps lines readable. ~70 chars per line is the
     comfortable upper bound for body copy. */
  max-width: 70ch;
}

.values-block:last-child {
  margin-bottom: 0;
}

.values-eyebrow {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.25em;
  color: var(--silver-dim);
  text-transform: uppercase;
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border-subtle);
  margin-bottom: var(--space-6);
}

.values-prose p {
  font-size: var(--text-lg);
  line-height: 1.7;
  color: var(--text-body);
  margin-bottom: var(--space-4);
}

.values-prose p:last-child {
  margin-bottom: 0;
}

.values-prose strong {
  color: var(--text-primary);
  font-weight: 700;
}

.values-link {
  color: var(--red);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: text-decoration-thickness var(--duration-fast) var(--ease-out);
}

.values-link:hover {
  text-decoration-thickness: 2px;
}


/* ----- RESOURCE CARDS ----- */

.resources-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
  margin-top: var(--space-8);
  /* Resources sit a bit narrower than the prose for emphasis but not
     so narrow they feel cramped. */
  max-width: 56rem;
}

.resource-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-6) var(--space-5);
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  text-decoration: none;
  color: inherit;
  transition: border-color var(--duration-normal) var(--ease-out),
              transform   var(--duration-fast) var(--ease-out);
}

.resource-card:hover {
  border-color: var(--border-strong);
  transform: translateY(-2px);
}

.resource-card:hover .corner {
  background: var(--silver);
}

/* The crisis card gets a slightly more prominent treatment — red left
   border to signal "this is the urgent one" without being alarmist
   about it. The whole card otherwise reads quiet. */
.resource-crisis {
  border-left: 3px solid var(--red);
}

.resource-crisis:hover .corner {
  background: var(--red);
}

.resource-label {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--silver-dim);
}

.resource-name {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--text-primary);
}

.resource-crisis .resource-name {
  color: var(--red);
}

.resource-desc {
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--text-body);
  flex: 1;
  margin-bottom: var(--space-2);
}

.resource-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: auto;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--silver);
}

.resource-card:hover .cta-arrow {
  transform: translateX(4px);
}


/* ============================================================================
   10h. JOIN / TIERS SECTION
   ============================================================================
   Three pricing cards in a row. The middle card (Creator) is the
   highlighted "MOST POPULAR" pick — slightly elevated, red border,
   badge above the title.

   Standard pricing-card UX: equal-height columns, big price as visual
   anchor, short benefit list with checkmarks, single clear CTA.
   ============================================================================ */

.join-title {
  font-size: clamp(var(--text-3xl), 4vw, var(--text-5xl));
  margin-bottom: var(--space-4);
  max-width: 24ch;
}

.join-intro {
  font-size: var(--text-lg);
  color: var(--text-body);
  max-width: 60ch;
  margin-bottom: var(--space-12);
}

.tier-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-6);
  /* `align-items: stretch` (the default for grid) makes all three cards
     match the tallest, so prices and CTAs line up across columns. */
}

.tier-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-8) var(--space-6);
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  transition: border-color var(--duration-normal) var(--ease-out),
              transform   var(--duration-fast) var(--ease-out);
}

.tier-card:hover {
  border-color: var(--border-strong);
  transform: translateY(-2px);
}

.tier-card:hover .corner {
  background: var(--silver);
}

/* THE POPULAR CARD — center tier gets visual prominence:
     • Red border (instead of silver-ish default)
     • Slight elevation (translateY) even at rest
     • Subtle red glow shadow
     • MOST POPULAR badge above the card top edge
   This is the standard pricing-table pattern because it works — it
   gives visitors permission to pick the middle option. */
.tier-popular {
  border-color: var(--red);
  transform: translateY(-8px);
  box-shadow: 0 8px 32px rgba(230, 57, 70, 0.15);
}

.tier-popular:hover {
  border-color: var(--red-bright);
  transform: translateY(-10px);
}

.tier-popular .corner {
  background: var(--red);
}

.tier-popular-badge {
  position: absolute;
  top: -12px;
  left: 50%;
  transform: translateX(-50%);
  padding: 4px var(--space-3);
  background: var(--red);
  color: var(--bg-primary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.15em;
  white-space: nowrap;
}

/* ----- HEADER ----- */

.tier-header {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
}

.tier-name {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text-primary);
  margin: 0;
}

.tier-popular .tier-name {
  color: var(--red);
}

.tier-purpose {
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--text-muted);
  margin: 0;
  /* min-height keeps cards aligned even when one purpose line is shorter */
  min-height: 2.6em;
}

/* ----- PRICE ----- */

.tier-price {
  display: flex;
  align-items: baseline;
  gap: var(--space-1);
  font-family: var(--font-mono);
  margin-top: var(--space-2);
}

.tier-price-amount {
  font-size: var(--text-4xl);
  font-weight: 700;
  letter-spacing: -0.03em;
  color: var(--text-primary);
}

.tier-price-unit {
  font-size: var(--text-base);
  color: var(--text-muted);
}

.tier-price-note {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-muted);
  letter-spacing: 0.05em;
  margin-top: -2px;
}

/* ----- BENEFITS ----- */

.tier-benefits {
  list-style: none;
  padding: 0;
  margin: var(--space-4) 0 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.tier-benefits li {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  font-size: var(--text-base);
  line-height: 1.4;
  color: var(--text-body);
}

.tier-check {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  color: var(--silver);
  font-size: var(--text-xs);
  font-weight: 700;
  margin-top: 2px;
}

.tier-popular .tier-check {
  background: var(--red);
  border-color: var(--red);
  color: var(--bg-primary);
}

.tier-more {
  display: inline-block;
  margin-top: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--silver-dim);
  transition: color var(--duration-fast) var(--ease-out);
}

.tier-more:hover {
  color: var(--silver);
}

/* The CTA pinned to bottom of the card — `margin-top: auto` is the
   flex trick for "push this to the bottom" inside a flex column. */
.tier-cta {
  margin-top: auto;
  justify-content: center;
}


/* ============================================================================
   10i. ABOUT PAGE
   ============================================================================
   Styles for /about/index.html. The page reuses many existing classes
   (.section, .section-label, .about-photo, .readout-corners) plus
   introduces these page-specific bits:

     • .page-hero          — small intro hero with breadcrumb
     • .breadcrumb         — Home / About marker
     • .story-grid         — origin section two-column layout
     • .timeline           — vertical timeline with dots and connecting line
     • .principles-grid    — 2×2 grid of principle cards
     • .now-block          — "currently working on" list
     • .connect-grid       — 3-up CTA cards at page end
   ============================================================================ */

/* ----- PAGE HERO ----- */

.page-hero {
  position: relative;
  padding-top: calc(var(--nav-height) + var(--space-16));
  padding-bottom: var(--space-16);
  overflow: hidden;
}

.page-hero-bg {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right,  rgba(200, 200, 200, 0.04) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(200, 200, 200, 0.04) 1px, transparent 1px),
    radial-gradient(ellipse at 70% 30%, var(--red-tint), transparent 60%);
  background-size: 60px 60px, 60px 60px, 100% 100%;
  mask-image: radial-gradient(ellipse at center, black 50%, transparent 100%);
  -webkit-mask-image: radial-gradient(ellipse at center, black 50%, transparent 100%);
}

.page-hero .section-container {
  position: relative;
  z-index: 1;
}

.breadcrumb {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.1em;
  color: var(--text-muted);
  margin-bottom: var(--space-6);
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.breadcrumb a {
  color: var(--silver);
  transition: color var(--duration-fast) var(--ease-out);
}

.breadcrumb a:hover {
  color: var(--red);
}

.breadcrumb-sep {
  color: var(--text-dim);
}

.breadcrumb-current {
  color: var(--text-body);
}

.page-hero-title {
  font-family: var(--font-display);
  font-size: clamp(var(--text-4xl), 6vw, var(--text-6xl));
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--text-primary);
  max-width: 18ch;
  margin: var(--space-6) 0 var(--space-6);
}

.page-hero-lede {
  font-size: var(--text-lg);
  line-height: 1.6;
  color: var(--text-body);
  max-width: 60ch;
  margin: 0;
}


/* ----- ORIGIN STORY ----- */

.story-grid {
  display: grid;
  /* Prose column gets noticeably more space than the photo column.
     The previous 1.4fr / 1fr ratio gave the photo too much room on
     wide screens. 2fr / 1fr keeps the prose dominant — the page is
     about the words; the photo is supportive imagery, not a hero. */
  grid-template-columns: 2fr 1fr;
  gap: var(--space-12);
  align-items: start;
}

.story-title {
  font-family: var(--font-display);
  font-size: clamp(var(--text-3xl), 4vw, var(--text-5xl));
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--text-primary);
  margin-bottom: var(--space-6);
}

.story-prose p {
  font-size: var(--text-base);
  line-height: 1.7;
  color: var(--text-body);
  margin-bottom: var(--space-4);
  max-width: 60ch;
}

.story-prose p:last-child {
  margin-bottom: 0;
}

.story-prose strong {
  color: var(--text-primary);
  font-weight: 700;
}

.story-prose em {
  color: var(--silver);
  font-style: normal;
  letter-spacing: 0.02em;
}

/* PHOTO COLUMN — supports one or more photo slots.
   Each photo is hard-capped at 320px wide so it never dominates.
   The whole column is also capped so on ultra-wide screens it doesn't
   drift far from the prose it accompanies. */
.story-photo-col {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  margin-top: var(--space-12);
  /* Hard cap on the column itself so the photo never gets bigger
     than ~320px on any viewport, even if the grid column allows more. */
  max-width: 320px;
  /* Center the column inside its grid cell so it doesn't hug the
     left edge if the grid gives it extra room. */
  margin-left: auto;
  margin-right: auto;
  /* Sticky so the photos stay in view as the long prose scrolls past
     them — small touch but it makes the column feel less abandoned
     once the reader gets a few paragraphs in. */
  position: sticky;
  top: calc(var(--nav-height) + var(--space-8));
}

.story-photo-caption {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
  text-align: center;
}

/* PHOTO ITEM — wraps a single photo + caption so multiple photos
   stack cleanly in the column with consistent spacing. */
.story-photo-item {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}


/* ----- TIMELINE ----- */

.timeline-title {
  margin-bottom: var(--space-12);
  font-size: clamp(var(--text-3xl), 4vw, var(--text-5xl));
}

.timeline {
  list-style: none;
  padding: 0;
  margin: 0;
  position: relative;
  border-left: 1px solid var(--border-default);
  margin-left: 8px;
  padding-left: var(--space-8);
}

.timeline-item {
  position: relative;
  padding-bottom: var(--space-12);
}

.timeline-item:last-child {
  padding-bottom: 0;
}

.timeline-dot {
  position: absolute;
  top: 8px;
  left: calc(-1 * var(--space-8) - 5px);
  width: 11px;
  height: 11px;
  background: var(--bg-primary);
  border: 2px solid var(--silver-dim);
  border-radius: 50%;
  transition: border-color var(--duration-normal) var(--ease-out),
              background var(--duration-normal) var(--ease-out);
}

.timeline-item:hover .timeline-dot {
  border-color: var(--red);
  background: var(--red);
}

.timeline-now .timeline-dot {
  border-color: var(--red);
  background: var(--red);
}

.timeline-content {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.timeline-year {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.2em;
  color: var(--silver-dim);
  text-transform: uppercase;
}

.timeline-now .timeline-year {
  color: var(--red);
}

.timeline-event {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text-primary);
  margin: 0;
  line-height: 1.2;
}

.timeline-desc {
  font-size: var(--text-base);
  line-height: 1.6;
  color: var(--text-body);
  max-width: 60ch;
  margin: 0;
}


/* ----- PRINCIPLES ----- */

.principles-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-4);
}

.principle-card {
  position: relative;
  padding: var(--space-8) var(--space-6);
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  transition: border-color var(--duration-normal) var(--ease-out),
              transform   var(--duration-fast) var(--ease-out);
}

.principle-card:hover {
  border-color: var(--border-strong);
  transform: translateY(-2px);
}

.principle-card:hover .corner {
  background: var(--red);
}

.principle-num {
  position: absolute;
  top: var(--space-4);
  right: var(--space-6);
  font-family: var(--font-mono);
  font-size: var(--text-3xl);
  font-weight: 700;
  color: var(--text-dim);
  letter-spacing: -0.02em;
  transition: color var(--duration-normal) var(--ease-out);
}

.principle-card:hover .principle-num {
  color: var(--red);
}

.principle-name {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: -0.01em;
  margin-bottom: var(--space-3);
  padding-right: var(--space-12);
  line-height: 1.2;
}

.principle-desc {
  font-size: var(--text-base);
  line-height: 1.6;
  color: var(--text-body);
  max-width: 50ch;
  margin: 0;
}


/* ----- "CURRENTLY" / NOW SECTION ----- */

.now-block {
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-left: 4px solid var(--red);
  padding: var(--space-8) var(--space-12);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.now-eyebrow {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.25em;
  color: var(--silver-dim);
  text-transform: uppercase;
}

.now-title {
  font-family: var(--font-display);
  font-size: clamp(var(--text-2xl), 3vw, var(--text-4xl));
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--text-primary);
  margin: 0;
}

.now-list {
  list-style: none;
  padding: 0;
  margin: var(--space-2) 0 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.now-list li {
  font-size: var(--text-base);
  line-height: 1.6;
  color: var(--text-body);
  padding-left: var(--space-6);
  position: relative;
}

.now-list li::before {
  content: "";
  position: absolute;
  top: 10px;
  left: 0;
  width: 6px;
  height: 6px;
  background: var(--red);
}

.now-list strong {
  color: var(--text-primary);
  font-weight: 700;
}

.now-list code {
  font-family: var(--font-mono);
  font-size: 0.95em;
  background: var(--bg-elevated);
  padding: 1px 6px;
  border: 1px solid var(--border-default);
  color: var(--silver);
}


/* ----- CONNECT — 3-up CTA cards ----- */

.connect-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-4);
}

.connect-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-6);
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  text-decoration: none;
  color: inherit;
  transition: border-color var(--duration-normal) var(--ease-out),
              transform   var(--duration-fast) var(--ease-out);
}

.connect-card:hover {
  border-color: var(--red);
  transform: translateY(-2px);
}

.connect-card:hover .corner {
  background: var(--red);
}

.connect-card:hover .cta-arrow {
  transform: translateX(4px);
}

.connect-eyebrow {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--silver-dim);
}

.connect-name {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.01em;
  margin: 0;
}

.connect-desc {
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--text-body);
  margin: 0;
  flex: 1;
}

.connect-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--silver);
}


/* ============================================================================
   10j. AFFILIATES & PARTNERS PAGE
   ============================================================================
   Styles for /affiliates/index.html. Reuses page-hero, breadcrumb, and
   section-label classes from the About page (10i), plus introduces:

     • .partners-grid       — 2-up grid of affiliate cards
     • .partner-card        — affiliate brand card with logo, code, CTA
     • .partner-code        — discount code display block
     • .clients-grid        — 2-up grid for client/working-with cards
     • .client-card         — slightly different visual treatment than
                              .partner-card so the two sections don't
                              read as one big list
     • .partner-cta-block   — page-end "want to partner?" CTA

   The cards reach a comfortable max width via the section-container,
   then collapse cleanly to single-column on tablet/mobile.
   ============================================================================ */

.partners-title {
  margin-bottom: var(--space-12);
  font-size: clamp(var(--text-3xl), 4vw, var(--text-5xl));
}

.partners-intro {
  font-size: var(--text-lg);
  line-height: 1.6;
  color: var(--text-body);
  max-width: 60ch;
  margin: var(--space-2) 0 var(--space-8);
}

.partners-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-6);
}

/* ----- AFFILIATE CARD ----- */

.partner-card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  transition: border-color var(--duration-normal) var(--ease-out),
              transform   var(--duration-fast) var(--ease-out);
}

.partner-card:hover {
  border-color: var(--red);
  transform: translateY(-2px);
}

.partner-card:hover .corner {
  background: var(--red);
}

/* "Coming soon" cards visually de-emphasize so they don't compete
   with active partners. Slightly muted, subtle dashed border. */
.partner-card-pending {
  opacity: 0.7;
}

.partner-card-pending:hover {
  border-color: var(--border-strong);
  transform: translateY(-2px);
}

.partner-pending-badge {
  display: inline-block;
  padding: 4px 10px;
  background: var(--bg-elevated);
  border: 1px solid var(--silver-dim);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.15em;
  color: var(--silver);
  margin-bottom: var(--space-3);
  align-self: flex-start;
}

/* LOGO area — sits at the top of the card, centered. Caps at a
   reasonable height so a tall logo doesn't blow the card up. */
.partner-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 120px;
  padding: var(--space-6);
  background: var(--bg-elevated);
  border-bottom: 1px solid var(--border-default);
}

.partner-logo img {
  max-width: 100%;
  max-height: 80px;
  width: auto;
  height: auto;
  display: block;
  filter: saturate(0.9);
  transition: filter var(--duration-slow) var(--ease-out);
}

.partner-card:hover .partner-logo img {
  filter: saturate(1);
}

/* Fallback shown if the logo image fails to load — display name in
   our display font, looks intentional rather than broken. */
.partner-logo-fallback {
  display: none;  /* shown by JS onerror handler when image fails */
  align-items: center;
  justify-content: center;
}

.fallback-name {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--silver);
}

/* BODY — name, description, optional code block, CTA */
.partner-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-6);
  flex: 1;
}

.partner-name {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--text-primary);
  margin: 0;
}

.partner-desc {
  font-size: var(--text-base);
  line-height: 1.6;
  color: var(--text-body);
  margin: 0;
  flex: 1;
}

/* CODE BLOCK — visually distinct so a visitor can find it instantly.
   Monospace value, red accent, label and detail in muted text. */
.partner-code {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  border-left: 3px solid var(--red);
  margin-top: var(--space-2);
}

.partner-code-label {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--silver-dim);
}

.partner-code-value {
  font-family: var(--font-mono);
  font-size: var(--text-lg);
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--red);
  background: transparent;
  padding: 0;
  border: 0;
  /* Make it visually obvious the code is selectable text — visitors
     will want to copy/paste. */
  user-select: all;
}

.partner-code-detail {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-muted);
  letter-spacing: 0.05em;
  flex-basis: 100%;  /* drops to its own line below the label + value */
}

.partner-cta {
  margin-top: var(--space-2);
  align-self: flex-start;
}


/* ----- CLIENTS GRID ("Working With") ----- */

.clients-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-6);
}

.client-card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  /* Subtle differentiator from affiliate cards: a thin silver left
     border so the section reads as "different category" without
     needing a different shape. */
  border-left: 3px solid var(--silver-dim);
  transition: border-color var(--duration-normal) var(--ease-out),
              transform   var(--duration-fast) var(--ease-out);
}

.client-card:hover {
  border-color: var(--silver);
  border-left-color: var(--silver);
  transform: translateY(-2px);
}

.client-card:hover .corner {
  background: var(--silver);
}

.client-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100px;
  padding: var(--space-5);
  background: var(--bg-elevated);
  border-bottom: 1px solid var(--border-default);
}

.client-logo img {
  max-width: 100%;
  max-height: 60px;
  width: auto;
  height: auto;
  display: block;
  filter: saturate(0.9);
  transition: filter var(--duration-slow) var(--ease-out);
}

.client-card:hover .client-logo img {
  filter: saturate(1);
}

.client-logo-fallback {
  display: none;  /* shown by JS onerror handler */
  align-items: center;
  justify-content: center;
}

.client-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-6);
  flex: 1;
}

.client-relationship {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--silver-dim);
}

.client-name {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--text-primary);
  margin: 0;
}

.client-desc {
  font-size: var(--text-base);
  line-height: 1.6;
  color: var(--text-body);
  margin: 0;
  flex: 1;
}

.client-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--silver);
  align-self: flex-start;
}

.client-link:hover {
  color: var(--red);
}


/* ----- PAGE-END "WANT TO PARTNER?" CTA ----- */

.partner-cta-section {
  /* Tighten the bottom of the page since this is the last section
     before the footer. */
  padding-bottom: var(--space-16);
}

.partner-cta-block {
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-left: 4px solid var(--red);
  padding: var(--space-8) var(--space-12);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  align-items: flex-start;
}

.partner-cta-prose {
  font-size: var(--text-base);
  line-height: 1.7;
  color: var(--text-body);
  max-width: 60ch;
  margin: 0;
}


/* ============================================================================
   10k. RECOMMENDATIONS PAGE
   ============================================================================
   Styles for /recommendations/index.html — a four-section reference
   page with ~40 small cards. Each section has a category color and
   a category icon to add visual rhythm and help visitors scan.

   Category color system: each section sets a --rec-accent CSS variable
   that cards inside cascade from. Cards use --rec-accent for hover
   borders, icon color, and corner brackets — so a single variable
   change drives the entire card's accent.

     • Software        → #348AA7 (teal blue, "tech/digital")
     • Web Services    → #5DD39E (mint green, "online/cloud")
     • Hardware        → #EDAE49 (amber, "physical/workshop")
     • Community       → #E63946 (red, brand — "yours")

   Card design principle: text-only (no logos), 3-up grid on desktop,
   focused on name + icon + description + link. Icon sits subtly in
   the top-right corner at low opacity, brightens on hover.
   ============================================================================ */

/* Per-section accent variables — each .recs-section[data-category="..."]
   overrides --rec-accent, which the .rec-card descendants pick up. */
.recs-section {
  --rec-accent: var(--red);  /* default fallback */
}

.recs-section[data-category="software"]    { --rec-accent: #348AA7; }
.recs-section[data-category="web"]         { --rec-accent: #5DD39E; }
.recs-section[data-category="hardware"]    { --rec-accent: #EDAE49; }
.recs-section[data-category="community"]   { --rec-accent: #E63946; }

/* QUICK NAV — anchor links in the hero so visitors can jump to a
   specific section without scrolling through the whole page. */
.recs-quicknav {
  list-style: none;
  padding: 0;
  margin: var(--space-6) 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

/* Each chip uses its own per-link accent color — visitors see the
   palette in the hero before they encounter it section by section. */
.recs-quicknav a {
  display: inline-flex;
  align-items: center;
  padding: var(--space-2) var(--space-4);
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--silver);
  transition: all var(--duration-fast) var(--ease-out);
}

.recs-quicknav a:hover {
  background: var(--quicknav-color, var(--red));
  border-color: var(--quicknav-color, var(--red));
  color: var(--bg-primary);
  transform: translateY(-1px);
}

/* Each quicknav chip has an inline style or class assigning its color */
.recs-quicknav a[data-cat="software"]:hover  { background: #348AA7; border-color: #348AA7; }
.recs-quicknav a[data-cat="web"]:hover       { background: #5DD39E; border-color: #5DD39E; }
.recs-quicknav a[data-cat="hardware"]:hover  { background: #EDAE49; border-color: #EDAE49; }
.recs-quicknav a[data-cat="community"]:hover { background: #E63946; border-color: #E63946; }

/* RECS SECTION TITLE */
.recs-title {
  margin-bottom: var(--space-8);
  font-size: clamp(var(--text-3xl), 4vw, var(--text-5xl));
}

/* GRID — 3 columns on desktop, 2 on tablet, 1 on mobile (handled in
   media queries). Smaller gap than other grids on the site so the
   page feels denser without being cramped. */
.recs-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-4);
}

/* REC CARD — the workhorse. Compact, scannable, uses --rec-accent
   from its parent section for color. */
.rec-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  /* The accent shows up as a tiny stripe along the top edge — subtle
     visual signal that this card belongs to a category, before the
     hover state fully reveals the color. */
  border-top: 2px solid var(--rec-accent, var(--red));
  transition: border-color var(--duration-normal) var(--ease-out),
              transform   var(--duration-fast) var(--ease-out),
              box-shadow  var(--duration-normal) var(--ease-out);
}

.rec-card:hover {
  border-color: var(--rec-accent, var(--red));
  border-top-color: var(--rec-accent, var(--red));
  transform: translateY(-2px);
  /* Soft glow in the section's accent color — picks up where the
     border-top stripe already established the color identity. */
  box-shadow: 0 4px 16px color-mix(in srgb, var(--rec-accent) 15%, transparent);
}

.rec-card:hover .corner {
  background: var(--rec-accent, var(--red));
}

/* CATEGORY ICON — sits in the top-right corner of each card.
   Subtle by default (low opacity, silver-dim color), brightens to
   the section accent color on hover. The card's parent section
   determines which icon shows via CSS background-image — but since
   we use inline SVG in the markup, this is just for the color. */
.rec-icon {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  width: 18px;
  height: 18px;
  color: var(--silver-dim);
  opacity: 0.5;
  transition: color var(--duration-normal) var(--ease-out),
              opacity var(--duration-normal) var(--ease-out);
  pointer-events: none;  /* don't block clicks on whatever's underneath */
}

.rec-card:hover .rec-icon {
  color: var(--rec-accent, var(--red));
  opacity: 1;
}

.rec-name {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--text-primary);
  margin: 0;
  line-height: 1.2;
  /* Reserve space on the right so a long name doesn't crash into the icon */
  padding-right: var(--space-8);
}

.rec-desc {
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--text-body);
  margin: 0;
  flex: 1;  /* push the link to the bottom of the card */
}

/* Optional warning line for items that need a compatibility note */
.rec-warning {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.05em;
  padding: var(--space-2) var(--space-3);
  background: var(--bg-elevated);
  border-left: 2px solid var(--rec-accent, var(--red));
  color: var(--silver);
  margin: 0;
}

/* META row — used for affiliate codes/notes below the description. */
.rec-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--bg-elevated);
  border-left: 2px solid var(--rec-accent, var(--red));
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}

.rec-affiliate {
  display: inline-block;
  padding: 1px 6px;
  background: var(--rec-accent, var(--red));
  color: var(--bg-primary);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
}

.rec-meta-detail {
  color: var(--text-muted);
  letter-spacing: 0.04em;
}

.rec-meta-detail code {
  display: inline;
  background: transparent;
  padding: 0;
  border: 0;
  color: var(--rec-accent, var(--red));
  font-weight: 700;
  user-select: all;  /* one-click copy */
}

/* LINK — sits at the bottom of the card. */
.rec-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: auto;
  padding-top: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--silver);
  transition: color var(--duration-fast) var(--ease-out);
}

.rec-link:hover {
  color: var(--rec-accent, var(--red));
}

.rec-link:hover .cta-arrow {
  transform: translateX(4px);
}

/* The "(affiliate)" tag inline on Amazon links — small, subtle,
   meets the FTC disclosure requirement without screaming. */
.rec-amazon-tag {
  display: inline-block;
  padding: 1px 5px;
  margin: 0 var(--space-1);
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  font-size: 9px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--silver-dim);
  font-weight: 600;
}

/* DISCLOSURE — the "Hardware links are Amazon affiliate" panel at the
   top of the hardware section. Uses the section accent color. */
.recs-disclosure {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  align-items: flex-start;
  padding: var(--space-4) var(--space-5);
  margin-bottom: var(--space-8);
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-left: 3px solid var(--rec-accent, var(--red));
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--text-body);
  max-width: 80ch;
}

.recs-disclosure-tag {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  background: var(--rec-accent, var(--red));
  color: var(--bg-primary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  flex-shrink: 0;
  height: 22px;
  margin-top: 1px;
}

.recs-disclosure strong {
  color: var(--text-primary);
}

/* COMMUNITY ATTRIBUTION — same vibe as disclosure but uses the
   community section's accent (red, in our palette). */
.recs-attribution {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  align-items: flex-start;
  padding: var(--space-4) var(--space-5);
  margin-bottom: var(--space-8);
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-left: 3px solid var(--rec-accent, var(--red));
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--text-body);
  max-width: 80ch;
}

.recs-attribution-tag {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  background: var(--rec-accent, var(--red));
  color: var(--bg-primary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  flex-shrink: 0;
  height: 22px;
  margin-top: 1px;
}

.recs-attribution a {
  color: var(--rec-accent, var(--red));
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}


/* ============================================================================
   10L. PORTFOLIO PAGE
   ============================================================================
   Styles for /portfolio/index.html. Reuses page-hero, breadcrumb,
   principle-card classes from earlier sections. Introduces:

     • .featured-carousel  — flowing card carousel for hero pieces
     • .featured-slide     — individual slide with background image
     • .carousel-btn       — prev/next navigation buttons
     • .thumb-strip        — click-to-jump thumbnails below carousel
     • .work-grid          — filterable thumbnail grid for "more work"
     • .work-filters       — filter pill buttons
     • .work-card          — individual thumbnail in the more-work grid
     • .portfolio-lightbox-frame — image-specific lightbox styling

   The carousel uses DOM order shuffling for navigation (next button
   moves first slide to end) so CSS just styles based on :nth-child.
   No "active index" state to track.
   ============================================================================ */



/* ----- FEATURED WORK CAROUSEL ----- */

/*
   Inspired by https://codepen.io/Wizard3000/pen/ZEPRoQd, restyled to
   our visual vocabulary. The active slide expands to fill the entire
   carousel area; upcoming slides stack to the right as smaller cards.

   How the slide order shuffling works:
     • At rest, the slides are ordered 1, 2, 3, 4 (left to right, with
       slide 2 being the "active" one filling the background)
     • Click "next": slide 1 is moved to the END of the list (becoming
       the rightmost off-screen card). Now the order is 2, 3, 4, 1.
       Slide 3 (the new :nth-child(2)) becomes active.
     • Click "prev": the last slide is moved to the START of the list.
       Order becomes 4, 1, 2, 3. Slide 1 becomes active.
   This DOM-shuffling approach (vs. tracking an "active index") keeps
   the CSS simple — it just styles based on :nth-child, no JS-driven
   class swapping needed.
*/

.featured-title-section {
  margin-bottom: var(--space-12);
  font-size: clamp(var(--text-3xl), 4vw, var(--text-5xl));
}

.featured-carousel-wrap {
  position: relative;
  width: 100%;
  /* Fixed height — the active slide fills this entirely. 16:9 ratio
     equivalent at our content width; clamp keeps it sensible across
     viewport sizes without ever getting too tall. */
  height: clamp(420px, 60vh, 680px);
  margin-bottom: var(--space-8);
  /* Hide overflow — the off-screen slides on the right edge get cut
     off cleanly rather than pushing content off the page. */
  overflow: hidden;
  /* Subtle border ties it to the rest of the page's vocabulary */
  border: 1px solid var(--border-default);
  background: var(--bg-surface);
}

.featured-carousel {
  position: relative;
  width: 100%;
  height: 100%;
  list-style: none;
  padding: 0;
  margin: 0;
}

/* Each slide is absolutely positioned. Default state (slides 3, 4, 5+)
   are small cards stacked to the right of the active one. */
.featured-slide {
  position: absolute;
  top: 50%;
  width: 220px;
  height: 320px;
  transform: translateY(-50%);
  z-index: 1;
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  /* The flow transition is what makes this carousel feel cinematic.
     1.75s matches the source — fast enough to feel responsive, slow
     enough to feel deliberate. */
  transition: transform 0.1s,
              left      1.75s,
              top       1.75s,
              width     1.75s,
              height    1.75s,
              border-color 1.75s,
              opacity   1.75s;
  overflow: hidden;
}

/* Active slide and the one currently animating in fill the entire
   carousel area. Both :nth-child(1) and (2) get this treatment so
   the transition smoothly hands off between them as slides shuffle. */
.featured-slide:nth-child(1),
.featured-slide:nth-child(2) {
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  transform: none;
  border-color: var(--red);  /* active gets red accent */
}

/* The 3rd slide sits just to the right of center as the next preview */
.featured-slide:nth-child(3) {
  left: 60%;
}

.featured-slide:nth-child(4) {
  left: calc(60% + 240px);
}

.featured-slide:nth-child(5) {
  left: calc(60% + 480px);
}

/* 6th and beyond fade out off the right edge */
.featured-slide:nth-child(n+6) {
  left: calc(60% + 720px);
  opacity: 0;
}

/* SLIDE BACKGROUND IMAGE — set via JS reading data-image attribute.
   Sits behind the content with a dark gradient overlay so text is
   always readable regardless of image content. */
.featured-slide-bg {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  background-color: var(--bg-elevated);  /* fallback when no image */
}

/* Gradient overlay — darker on the bottom-left where text sits,
   so even bright images keep good contrast for the headline. */
.featured-slide-bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(135deg,
      rgba(10, 10, 10, 0.85) 0%,
      rgba(10, 10, 10, 0.60) 40%,
      rgba(10, 10, 10, 0.20) 70%,
      rgba(10, 10, 10, 0.40) 100%);
}

/* When no image set yet, show a candy-stripe placeholder pattern */
.featured-slide:not([data-image=""]) .featured-slide-bg::after {
  /* if data-image is set, this rule applies */
}

.featured-slide[data-image=""] .featured-slide-bg {
  background:
    linear-gradient(45deg, rgba(230, 57, 70, 0.05) 25%, transparent 25%) 0 0 / 24px 24px,
    linear-gradient(-45deg, rgba(230, 57, 70, 0.05) 25%, transparent 25%) 0 0 / 24px 24px,
    var(--bg-elevated);
}

.featured-slide[data-image=""] .featured-slide-bg::after {
  background: none;  /* no gradient overlay on placeholder */
}

/* SLIDE CONTENT — title, description, meta, CTA. Hidden by default,
   shown only on the currently-active slide (:nth-of-type(2)). */
.featured-slide-content {
  position: absolute;
  bottom: var(--space-12);
  left: var(--space-12);
  max-width: 540px;
  z-index: 2;
  display: none;
  opacity: 0;
}

.featured-slide:nth-of-type(2) .featured-slide-content {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  /* Animate in shortly after the slide settles into place */
  animation: featured-slide-show 0.75s var(--ease-out) 0.4s forwards;
}

@keyframes featured-slide-show {
  0% {
    opacity: 0;
    filter: blur(8px);
    transform: translateY(20px);
  }
  100% {
    opacity: 1;
    filter: blur(0);
    transform: translateY(0);
  }
}

/* CORNER BRACKETS on the active slide — sharp, technical accent */
.featured-slide:nth-of-type(2)::before,
.featured-slide:nth-of-type(2)::after {
  content: "";
  position: absolute;
  width: 12px;
  height: 12px;
  border-color: var(--red);
  border-style: solid;
  z-index: 2;
}

.featured-slide:nth-of-type(2)::before {
  top: var(--space-4);
  left: var(--space-4);
  border-width: 1px 0 0 1px;
}

.featured-slide:nth-of-type(2)::after {
  bottom: var(--space-4);
  right: var(--space-4);
  border-width: 0 1px 1px 0;
}

/* The non-active slides show their image but no content overlay.
   A subtle gradient still applies so they look intentional. */
.featured-slide:nth-child(n+3) .featured-slide-content {
  display: none;
}

/* CONTENT TYPOGRAPHY — same vocabulary as everywhere else, white-ish
   on dark gradient overlay */
.featured-eyebrow {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--silver);
}

.featured-name {
  font-family: var(--font-display);
  font-size: clamp(var(--text-3xl), 4vw, var(--text-5xl));
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text-primary);
  margin: 0;
  line-height: 1.05;
}

.featured-desc {
  font-size: var(--text-base);
  line-height: 1.6;
  color: var(--text-body);
  margin: 0;
  max-width: 50ch;
}

.featured-meta {
  list-style: none;
  padding: var(--space-2) 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-6);
  border-top: 1px solid rgba(255, 255, 255, 0.15);
  border-bottom: 1px solid rgba(255, 255, 255, 0.15);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--silver);
  letter-spacing: 0.05em;
}

.featured-meta .meta-label {
  display: inline-block;
  margin-right: var(--space-1);
  color: var(--silver-dim);
  text-transform: uppercase;
  font-weight: 700;
  letter-spacing: 0.15em;
}

.featured-cta {
  align-self: flex-start;
  margin-top: var(--space-2);
}


/* CAROUSEL NAVIGATION — prev/next arrow buttons */

.carousel-nav {
  position: absolute;
  bottom: var(--space-6);
  right: var(--space-6);
  display: flex;
  gap: var(--space-2);
  z-index: 5;
}

.carousel-btn {
  width: 44px;
  height: 44px;
  background: rgba(10, 10, 10, 0.7);
  border: 1px solid var(--silver);
  color: var(--silver);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all var(--duration-fast) var(--ease-out);
  /* Backdrop blur lifts the buttons off whatever image is behind them */
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.carousel-btn:hover {
  background: var(--red);
  border-color: var(--red);
  color: var(--bg-primary);
}

.carousel-btn:focus-visible {
  outline: 2px solid var(--red);
  outline-offset: 2px;
}


/* THUMB STRIP — click-to-jump thumbnails below the carousel */

.thumb-strip {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-3);
}

.thumb-jump {
  /* Reset button defaults */
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  /* Layout */
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  transition: transform var(--duration-fast) var(--ease-out);
}

.thumb-jump:hover {
  transform: translateY(-2px);
}

.thumb-jump-img {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  display: flex;
  align-items: center;
  justify-content: center;
  background-size: cover;
  background-position: center;
  transition: border-color var(--duration-fast) var(--ease-out),
              opacity var(--duration-fast) var(--ease-out);
  opacity: 0.5;
}

.thumb-jump.is-active .thumb-jump-img {
  border-color: var(--red);
  opacity: 1;
}

.thumb-jump:hover .thumb-jump-img {
  border-color: var(--silver);
  opacity: 0.85;
}

/* Number shown when no real thumbnail image is set */
.thumb-jump-num {
  font-family: var(--font-mono);
  font-size: var(--text-xl);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--silver-dim);
}

.thumb-jump-name {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--silver-dim);
  transition: color var(--duration-fast) var(--ease-out);
  /* Truncate long names with ellipsis instead of wrapping */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.thumb-jump.is-active .thumb-jump-name {
  color: var(--red);
}

.thumb-jump:hover .thumb-jump-name {
  color: var(--silver);
}


/* ----- MORE WORK GRID (filterable) ----- */

.work-filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-8);
}

.work-filter {
  display: inline-flex;
  align-items: center;
  padding: var(--space-2) var(--space-4);
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--silver);
  cursor: pointer;
  transition: all var(--duration-fast) var(--ease-out);
}

.work-filter:hover {
  border-color: var(--red);
  color: var(--red);
}

.work-filter.is-active {
  background: var(--red);
  border-color: var(--red);
  color: var(--bg-primary);
}

/* The grid itself — 4 columns on desktop, collapses on smaller. */
.work-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-4);
}

/* Filter logic — when the grid has data-filter set to a category,
   hide work-cards whose data-type doesn't match. data-filter="all"
   shows everything (no rules apply). */
.work-grid[data-filter="overlay"] .work-card:not([data-type="overlay"]),
.work-grid[data-filter="widget"]  .work-card:not([data-type="widget"]),
.work-grid[data-filter="graphic"] .work-card:not([data-type="graphic"]),
.work-grid[data-filter="brand"]   .work-card:not([data-type="brand"]) {
  display: none;
}

.work-card {
  /* Reset button defaults */
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  /* Card layout */
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  transition: transform var(--duration-fast) var(--ease-out);
}

.work-card:hover {
  transform: translateY(-2px);
}

.work-thumb {
  position: relative;
  aspect-ratio: 4 / 3;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  overflow: hidden;
  transition: border-color var(--duration-normal) var(--ease-out);
}

.work-card:hover .work-thumb {
  border-color: var(--red);
}

.work-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform var(--duration-slow) var(--ease-out);
}

.work-card:hover .work-thumb img {
  transform: scale(1.05);
}

.work-thumb-placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  background: var(--bg-elevated);
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--silver-dim);
}

.work-thumb-placeholder small {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 400;
  letter-spacing: 0.1em;
  color: var(--text-muted);
  text-transform: uppercase;
}

.work-info {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

.work-name {
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: -0.005em;
}

.work-tag {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--silver-dim);
  padding: 2px 6px;
  border: 1px solid var(--border-default);
  flex-shrink: 0;
}


/* ----- PORTFOLIO LIGHTBOX (image-specific) ----- */

/* Reuses .lightbox base styles (10e) but the frame holds an image
   instead of an iframe, with a caption underneath. */
.portfolio-lightbox-frame {
  width: 100%;
  max-width: 1200px;
  aspect-ratio: auto;        /* let the image set its own height */
  max-height: 85vh;
  background: transparent;
  border: 0;
  box-shadow: none;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  align-items: center;
  justify-content: center;
}

.portfolio-lightbox-frame img {
  max-width: 100%;
  max-height: 80vh;
  width: auto;
  height: auto;
  display: block;
  border: 1px solid var(--border-strong);
  box-shadow: 0 0 0 1px var(--red), 0 30px 80px rgba(0, 0, 0, 0.6);
}

.portfolio-lightbox-caption {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  letter-spacing: 0.05em;
  color: var(--silver);
  margin: 0;
  text-align: center;
}


/* ============================================================================
   10M. COMMUNITY PAGE
   ============================================================================
   Styles for /community/index.html. Three distinct card layouts:

     • .person-card   — host/sponsored with circular avatar (Section 1)
     • .creator-card  — creator with square logo + dual links (Section 2)
     • .sub-tile      — subscriber tile, dense grid (Section 3)
     • .coming-soon-block — placeholder for Fourthwall (Section 4)

   The hosts and subs sections are JS-populated from JSON files. The
   creators section is hand-edited HTML. The Fourthwall section is a
   static "coming soon" block.

   Section 1 is split into TWO sub-sections (Hosts and Sponsored Hosts).
   Both render person-cards from the same hosts-cache.json file — JS
   filters by 'role' field to route each person into the right grid.

   The .person-card uses a circular avatar with a colored border
   (red for hosts, silver for sponsored) — visual signal of role tier
   without needing words.
   ============================================================================ */

.community-intro {
  font-size: var(--text-base);
  line-height: 1.6;
  color: var(--text-body);
  margin: 0 0 var(--space-8);
  max-width: 70ch;
}

/* Generic loading state for both JS-populated grids */
.people-loading {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  letter-spacing: 0.1em;
  color: var(--silver-dim);
  padding: var(--space-8);
  text-align: center;
  border: 1px dashed var(--border-default);
}

/* Same loading style works on both grids */
.subs-grid .people-loading {
  grid-column: 1 / -1;
}


/* ----- PEOPLE SUB-SECTIONS (Hosts and Sponsored Hosts grids) ----- */

/* Each sub-section is one grid + a heading above it. We use two of
   these stacked inside the [01] Thee Network section. */
.people-subsection {
  margin-bottom: var(--space-10);
}

.people-subsection:last-child {
  margin-bottom: 0;
}

/* The sub-section heading — smaller than the section's <h2> but
   still substantial. Uses the same red-tick eyebrow pattern as the
   "Now / Currently working on" headers in About. */
.people-subsection-title {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-family: var(--font-display);
  font-size: clamp(var(--text-xl), 2.2vw, var(--text-2xl));
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--text-primary);
  margin: 0 0 var(--space-5);
  /* Small red tick before the heading */
}

.subsection-tick {
  display: inline-block;
  width: 8px;
  height: 8px;
  background: var(--red);
  flex-shrink: 0;
}


/* ----- PEOPLE GRID (Hosts and Sponsored Hosts cards) ----- */

.people-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-4);
}

/* Each person — generated from JSON. Card structure includes circular
   avatar at top, name + badge in the header, description, tags, and
   a Twitch link footer. */
.person-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  /* Top accent stripe — red for hosts, silver for sponsored. Same
     visual treatment as the recommendations cards. */
  border-top: 2px solid var(--silver-dim);
  transition: border-color var(--duration-normal) var(--ease-out),
              transform   var(--duration-fast) var(--ease-out),
              box-shadow  var(--duration-normal) var(--ease-out);
}

.person-card[data-role="host"] {
  border-top-color: var(--red);
}

.person-card:hover {
  border-color: var(--silver);
  transform: translateY(-2px);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
}

.person-card[data-role="host"]:hover {
  border-color: var(--red);
  box-shadow: 0 4px 16px rgba(230, 57, 70, 0.15);
}

.person-card:hover .corner {
  background: var(--silver);
}

.person-card[data-role="host"]:hover .corner {
  background: var(--red);
}

/* Person header: avatar + name/badge stacked next to it */
.person-header {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.person-avatar {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--bg-elevated);
  border: 2px solid var(--silver-dim);
  flex-shrink: 0;
  object-fit: cover;
  /* When no avatar is set yet, a gradient shows */
  background-image: linear-gradient(135deg, var(--bg-elevated) 0%, var(--border-strong) 100%);
}

.person-card[data-role="host"] .person-avatar {
  border-color: var(--red);
}

.person-name-block {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.person-name {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 700;
  color: var(--text-primary);
  margin: 0;
  line-height: 1.1;
  /* Truncate if name is too long for the card */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.person-badge {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  padding: 1px 6px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--silver-dim);
}

.person-card[data-role="host"] .person-badge {
  background: var(--red);
  border-color: var(--red);
  color: var(--bg-primary);
}

.person-desc {
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--text-body);
  margin: 0;
  /* Limit to ~3 lines to keep cards uniform height */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  line-clamp: 3;
  overflow: hidden;
}

.person-tags {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
}

.person-tag {
  display: inline-block;
  padding: 1px 6px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.05em;
  color: var(--text-muted);
}

.person-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: auto;
  padding-top: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--silver);
  border-top: 1px solid var(--border-subtle);
  transition: color var(--duration-fast) var(--ease-out);
}

.person-link:hover {
  color: var(--red);
}

.person-link svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}



/* ----- CREATORS CAROUSEL (portfolio-style with flow animation) -----
 *
 * Visual model: the active creator's slide fills the entire carousel area.
 * The next 2 creators stack as smaller preview panels on the right side,
 * darkened to keep visual focus on the active slide. When you click next,
 * the flow animates over 1.2 seconds:
 *   - The active slide compresses into a small preview at the back of the line
 *   - Each preview moves one position forward
 *   - The frontmost preview expands to fill the area and lights up
 *
 * Mechanism (same as portfolio carousel): we shuffle DOM order via JS, and
 * CSS styles based on :nth-child. No "active index" variable to track.
 *   - :nth-child(1) is the active slide (fills the wrap)
 *   - :nth-child(2) is the closer preview
 *   - :nth-child(3) is the farther preview
 *   - :nth-child(n+4) is off-screen, fading out
 *
 * Background treatment per slide:
 *   - The avatar/logo is set via inline style as a background-image
 *   - A dark linear-gradient overlay sits on top via ::after pseudo-element
 *   - On preview slides, an additional brightness filter darkens everything
 *   - When a slide animates to active position, the filter lifts smoothly
 *
 * Content (name, description, links) lives in .creator-slide-content which
 * is only visible on the active slide (:nth-child(1)).
 */

.creators-carousel-wrap {
  position: relative;
  width: 100%;
  /* Fixed height — active slide fills this. Match portfolio for consistency. */
  height: clamp(420px, 55vh, 560px);
  margin-bottom: var(--space-6);
  overflow: hidden;
  border: 1px solid var(--border-default);
  background: var(--bg-surface);
}

.creators-carousel {
  position: relative;
  width: 100%;
  height: 100%;
  list-style: none;
  padding: 0;
  margin: 0;
}

/* The base slide. All slides are absolutely positioned. Default state
   (slides 4+) sit off-screen to the right and are invisible. */
.creator-slide {
  position: absolute;
  top: 50%;
  width: 200px;
  height: 280px;
  transform: translateY(-50%);
  z-index: 1;
  background-color: var(--bg-elevated);
  background-position: center;
  background-size: cover;
  border: 1px solid var(--border-strong);
  overflow: hidden;
  /* This is the flow animation. 1.2 seconds, matching the value you chose. */
  transition: left      1.2s var(--ease-out),
              top       1.2s var(--ease-out),
              width     1.2s var(--ease-out),
              height    1.2s var(--ease-out),
              filter    1.2s var(--ease-out),
              border-color 1.2s var(--ease-out),
              opacity   1.2s var(--ease-out),
              transform 0.1s var(--ease-out);
  /* Preview slides are darkened. The active slide will override this. */
  filter: brightness(0.4) saturate(0.8);
}

/* The dark gradient overlay — sits over the background image to give the
   slide depth and ensure text legibility on the active slide. The active
   slide will have a lighter gradient. */
.creator-slide::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg,
    rgba(10, 10, 10, 0.85) 0%,
    rgba(10, 10, 10, 0.55) 40%,
    rgba(10, 10, 10, 0.20) 70%,
    rgba(10, 10, 10, 0.40) 100%);
  transition: background 1.2s var(--ease-out);
  pointer-events: none;
  z-index: 1;
}

/* Active slide — fills the full area, full color, content visible */
.creator-slide:nth-child(1) {
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  transform: none;
  border-color: var(--red);
  filter: brightness(1) saturate(1);
}

/* Slightly less heavy gradient on active so the avatar/logo behind comes
   through more. Still dark enough to keep text readable. */
.creator-slide:nth-child(1)::after {
  background: linear-gradient(135deg,
    rgba(10, 10, 10, 0.78) 0%,
    rgba(10, 10, 10, 0.45) 40%,
    rgba(10, 10, 10, 0.15) 70%,
    rgba(10, 10, 10, 0.35) 100%);
}

/* First preview — closer to the right edge */
.creator-slide:nth-child(2) {
  left: 62%;
}

/* Second preview — further out */
.creator-slide:nth-child(3) {
  left: calc(62% + 220px);
}

/* Beyond preview 2 — fading off-screen */
.creator-slide:nth-child(n+4) {
  left: calc(62% + 440px);
  opacity: 0;
}

/* CORNER BRACKETS on the active slide — same vocabulary as elsewhere */
.creator-slide:nth-child(1)::before {
  content: "";
  position: absolute;
  top: var(--space-4);
  left: var(--space-4);
  width: 12px;
  height: 12px;
  border: 1px solid var(--red);
  border-right: none;
  border-bottom: none;
  z-index: 3;
}

/* SLIDE CONTENT — name, description, links. Only shown on the active slide.
   Hidden on previews via display: none AND opacity 0. */
.creator-slide-content {
  position: absolute;
  bottom: var(--space-8);
  left: var(--space-8);
  right: var(--space-8);
  max-width: 540px;
  z-index: 2;
  display: none;
  opacity: 0;
}

.creator-slide:nth-child(1) .creator-slide-content {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  /* Fade in 0.3s into the slide transition — feels like the content
     materializes after the slide settles into position. */
  animation: creator-slide-show 0.7s var(--ease-out) 0.3s forwards;
}

@keyframes creator-slide-show {
  0% {
    opacity: 0;
    filter: blur(6px);
    transform: translateY(15px);
  }
  100% {
    opacity: 1;
    filter: blur(0);
    transform: translateY(0);
  }
}

/* AVATAR — a circular logo image floating in the content area on the
   active slide. Sits on top of the gradient. */
.creator-slide-avatar {
  width: 84px;
  height: 84px;
  border-radius: 50%;
  background: var(--bg-elevated);
  background-size: cover;
  background-position: center;
  border: 2px solid var(--red);
  flex-shrink: 0;
}

.creator-slide-header {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

.creator-slide-name-block {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.creator-slide-name {
  font-family: var(--font-display);
  font-size: clamp(var(--text-2xl), 3vw, var(--text-4xl));
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text-primary);
  margin: 0;
  line-height: 1.1;
}

.creator-slide-username {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.05em;
  color: var(--silver);
}

.creator-slide-desc {
  font-size: var(--text-base);
  line-height: 1.6;
  color: var(--text-body);
  margin: 0;
  max-width: 60ch;
}

.creator-slide-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-2);
}

.creator-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: rgba(10, 10, 10, 0.6);
  border: 1px solid var(--silver-dim);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--silver);
  text-decoration: none;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  transition: all var(--duration-fast) var(--ease-out);
}

.creator-link:hover {
  border-color: var(--red);
  color: var(--red);
  background: rgba(10, 10, 10, 0.85);
}

.creator-link svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}

/* CAROUSEL NAVIGATION — same buttons as portfolio carousel */
.creators-carousel-wrap .carousel-nav {
  position: absolute;
  bottom: var(--space-6);
  right: var(--space-6);
  display: flex;
  gap: var(--space-2);
  z-index: 5;
}

/* POSITION COUNTER — top-right of the carousel ("3 / 8") */
.creators-counter {
  position: absolute;
  top: var(--space-4);
  right: var(--space-5);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.15em;
  color: var(--silver);
  z-index: 5;
  background: rgba(10, 10, 10, 0.6);
  padding: var(--space-1) var(--space-2);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  pointer-events: none;
}

/* LOADING STATE */
.creators-loading {
  list-style: none;
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  letter-spacing: 0.1em;
  color: var(--silver-dim);
}

/* REDUCED MOTION — respect user's OS preference. Disables the flow
   animation entirely; slides appear/disappear without transitioning. */
@media (prefers-reduced-motion: reduce) {
  .creator-slide {
    transition: none !important;
  }
  .creator-slide-content,
  .creator-slide:nth-child(1) .creator-slide-content {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
  }
}




/* ----- SUBSCRIBERS GRID (supporter wall — bigger cards with badges) -----
 *
 * Tier color system: each card gets a data-tier attribute (silver, white,
 * green, blue, purple, gold, red) reflecting longevity. Tiers thresholds
 * are computed in JS (computeSupporterTier). The CSS applies a per-tier
 * accent color via the --tier-color custom property, which drives both
 * the top border stripe AND a subtle 45° gradient on the card background.
 *
 * The gradient runs from dark (top-left) to a 12% tinted version of the
 * tier color (bottom-right). Subtle enough that text stays readable, but
 * visible enough to communicate "this person is at a different level."
 */

.subs-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: var(--space-3);
}

/* Per-tier accent colors. Each .sub-tile sets --tier-color via its
   data-tier attribute, and the rest of the styling references that var. */
.sub-tile[data-tier="silver"]  { --tier-color: #c8c8c8; }
.sub-tile[data-tier="white"]   { --tier-color: #f5f5f5; }
.sub-tile[data-tier="green"]   { --tier-color: #5dd39e; }
.sub-tile[data-tier="blue"]    { --tier-color: #3a8dd5; }
.sub-tile[data-tier="purple"]  { --tier-color: #9b59b6; }
.sub-tile[data-tier="gold"]    { --tier-color: #d4af37; }
.sub-tile[data-tier="red"]     { --tier-color: #e63946; }
.sub-tile                      { --tier-color: var(--silver-dim); }  /* fallback */

.sub-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4);
  /* The 45° gradient — dark at top-left, tier-color tinted at bottom-right.
     color-mix lets us blend the tier color with our base dark background
     at a specific opacity without manually computing rgba values. */
  background:
    linear-gradient(
      135deg,
      var(--bg-surface) 0%,
      var(--bg-surface) 45%,
      color-mix(in srgb, var(--tier-color) 15%, var(--bg-surface)) 100%
    );
  border: 1px solid var(--border-default);
  /* Top accent stripe in the tier color */
  border-top: 2px solid var(--tier-color);
  text-decoration: none;
  transition: border-color var(--duration-fast) var(--ease-out),
              transform    var(--duration-fast) var(--ease-out),
              box-shadow   var(--duration-fast) var(--ease-out);
}

.sub-tile:hover {
  transform: translateY(-2px);
  /* On hover, the border picks up more of the tier color */
  border-color: var(--tier-color);
  /* Glow in the tier color */
  box-shadow: 0 4px 12px color-mix(in srgb, var(--tier-color) 18%, transparent);
}

/* TOP ROW: avatar + name */
.sub-tile-header {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
  position: relative;
  z-index: 1;
}

.sub-avatar {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--bg-elevated);
  /* Avatar border picks up the tier color too — small but consistent */
  border: 2px solid var(--tier-color);
  flex-shrink: 0;
  object-fit: cover;
  background-size: cover;
  background-position: center;
  background-image: linear-gradient(135deg, var(--bg-elevated) 0%, var(--border-strong) 100%);
}

.sub-name {
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 700;
  color: var(--text-primary);
  line-height: 1.15;
  letter-spacing: -0.005em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

/* BADGES + NUMBERS ROW */
.sub-stats {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: auto;
  position: relative;
  z-index: 1;
}

.sub-stat {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 3px 8px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--silver);
}

.sub-stat svg {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
}

/* Subscriber badge — uses the tier color for an instant "they're here" cue.
   Bright tier colors get dark text; dark tier colors get light text. */
.sub-stat.is-sub {
  background: var(--tier-color);
  border-color: var(--tier-color);
  /* For light tier colors (silver, white, gold), use dark text. For dark
     ones (green, blue, purple, red), use light text. We use color-mix
     to compute a contrast color based on luminance — but the simpler
     heuristic is to override per-tier below. */
  color: var(--bg-primary);
}

/* Override badge text color for dark tier colors where bg-primary text
   would be too low contrast */
.sub-tile[data-tier="green"]  .sub-stat.is-sub,
.sub-tile[data-tier="blue"]   .sub-stat.is-sub,
.sub-tile[data-tier="purple"] .sub-stat.is-sub,
.sub-tile[data-tier="red"]    .sub-stat.is-sub {
  color: var(--text-primary);
}

/* Gifter badge — silver/neutral always (different role from subscriber).
   Doesn't take tier color so visitors can tell at a glance whether the
   tier comes from sub-months (red T badge in tier color) vs gifts. */
.sub-stat.is-gifter {
  background: var(--bg-elevated);
  border-color: var(--silver-dim);
  color: var(--silver);
}

/* Empty state */
.subs-empty {
  grid-column: 1 / -1;
  padding: var(--space-8);
  text-align: center;
  border: 1px dashed var(--border-default);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--silver-dim);
  letter-spacing: 0.05em;
}


/* ----- FOURTHWALL MEMBERS GRID -----
 *
 * Visual model: each card has a tier-themed gradient background (matching
 * the color palette of that tier's logo image), with the tier image
 * displayed prominently at the top of the card. Member nickname below.
 *
 * Tier gradients are sampled from the actual logo images:
 *   - Community ($1):    yellow → orange → red sweep (matches Elite Nerdcast logo)
 *   - Creator ($7.50):   pink/red → cyan diagonal (matches the "C" gradient)
 *   - Early Access ($10): orange family (matches the "EA" gradient)
 *
 * Same structural vocabulary as the Twitch sub wall (.sub-tile) — gradient
 * corner, top border stripe in tier color — but the tier image is the
 * focal point rather than an avatar circle.
 */

.members-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: var(--space-3);
  margin-bottom: var(--space-8);
}

/* Per-tier color custom properties.
 * --tier-stripe = the accent color for the top border + hover glow
 * --tier-bg-end = where the gradient ends up in the bottom-right corner
 *                 (a heavily-tinted version of tier-stripe blended with
 *                 the dark surface) */
.member-card[data-tier-id="mt_4838"] {
  /* Community — yellow/orange/red sweep */
  --tier-stripe: #dc6400;
  --tier-bg-end: color-mix(in srgb, #dc6400 22%, var(--bg-surface));
  --tier-bg-mid: color-mix(in srgb, #dcb400 15%, var(--bg-surface));
}

.member-card[data-tier-id="mt_21732"] {
  /* Creator — pink/red → cyan blue diagonal */
  --tier-stripe: #f03c50;
  --tier-bg-end: color-mix(in srgb, #3cb4f0 25%, var(--bg-surface));
  --tier-bg-mid: color-mix(in srgb, #f03c50 18%, var(--bg-surface));
}

.member-card[data-tier-id="mt_21733"] {
  /* Early Access — orange family */
  --tier-stripe: #f05028;
  --tier-bg-end: color-mix(in srgb, #f05028 25%, var(--bg-surface));
  --tier-bg-mid: color-mix(in srgb, #f0a064 12%, var(--bg-surface));
}

/* Fallback for any unknown tier (shouldn't happen with filtering, but defensive) */
.member-card {
  --tier-stripe: var(--silver-dim);
  --tier-bg-end: var(--bg-elevated);
  --tier-bg-mid: var(--bg-surface);
}

.member-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4);
  /* The tier-themed gradient. Three stops give a smoother transition
     than a simple two-stop linear gradient, especially for the Community
     tier which has multiple color phases (yellow → orange → red). */
  background:
    linear-gradient(
      135deg,
      var(--bg-surface) 0%,
      var(--bg-surface) 35%,
      var(--tier-bg-mid) 65%,
      var(--tier-bg-end) 100%
    );
  border: 1px solid var(--border-default);
  border-top: 2px solid var(--tier-stripe);
  text-decoration: none;
  transition: border-color var(--duration-fast) var(--ease-out),
              transform    var(--duration-fast) var(--ease-out),
              box-shadow   var(--duration-fast) var(--ease-out);
}

.member-card:hover {
  transform: translateY(-2px);
  border-color: var(--tier-stripe);
  box-shadow: 0 4px 14px color-mix(in srgb, var(--tier-stripe) 22%, transparent);
}

/* TIER IMAGE — sits at the top of the card.
 * All three logo images are 500x500 now (after the community re-export),
 * so a square aspect ratio works for all of them. Container has fixed
 * dimensions so cards line up neatly regardless of how the image's
 * natural dimensions vary. */
.member-tier-image {
  width: 120px;
  height: 120px;
  align-self: center;
  /* The image background is transparent or matches the logo's design;
     we let the card's tier-themed gradient show through behind it.
     object-fit: contain ensures the whole logo is visible without
     being cropped, which is important for the circular badge logos. */
  object-fit: contain;
  /* No background — let the card gradient show through */
}

/* MEMBER NICKNAME — main text below the image */
.member-name {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 700;
  color: var(--text-primary);
  text-align: center;
  line-height: 1.2;
  letter-spacing: -0.005em;
  /* Truncate very long nicknames */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* TIER NAME — small label below the nickname.
 * Color picks up the tier's accent for at-a-glance tier identification. */
.member-tier-name {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--tier-stripe);
  text-align: center;
}

/* TENURE — even smaller, optional, shows how long they've been a member
 * (e.g. "MEMBER SINCE MAR 2024"). Helps visitors see the variety in
 * member longevity. */
.member-since {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
  text-align: center;
  margin-top: auto;  /* pushes to bottom of card */
  padding-top: var(--space-2);
  border-top: 1px solid var(--border-subtle);
}

/* EMPTY STATE — shown if no members loaded or all filtered out */
.members-empty {
  grid-column: 1 / -1;
  padding: var(--space-12);
  text-align: center;
  border: 1px dashed var(--border-default);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--silver-dim);
  letter-spacing: 0.05em;
}

/* CTA AT BOTTOM */
.members-cta {
  display: flex;
  justify-content: center;
  margin-top: var(--space-6);
  position: relative;
  padding: var(--space-12) var(--space-8);
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-left: 3px solid var(--silver-dim);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  align-items: flex-start;
  max-width: 70ch;
}

.coming-soon-title {
  font-family: var(--font-display);
  font-size: clamp(var(--text-2xl), 3vw, var(--text-4xl));
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text-primary);
  margin: 0;
  line-height: 1.15;
}

.coming-soon-desc {
  font-size: var(--text-base);
  line-height: 1.6;
  color: var(--text-body);
  margin: 0;
  max-width: 60ch;
}


/* ============================================================================
   11. FOOTER
   ============================================================================
   Four-column structure on desktop, collapses progressively:
     desktop:   4 columns
     tablet:    2×2 grid
     mobile:    single column

   The bottom bar sits below the columns with copyright + crisis line
   (mirrors the values section's resources for visitors who scroll
   straight to the bottom).
   ============================================================================ */

.footer {
  padding: var(--space-16) 0 var(--space-8);
  border-top: 1px solid var(--border-default);
}

.footer-container {
  display: flex;
  flex-direction: column;
  gap: var(--space-12);
}

/* Four-column grid. The brand column is wider since it has the
   tagline + blurb. */
.footer-grid {
  display: grid;
  grid-template-columns: 1.5fr 1fr 1fr 1fr;
  gap: var(--space-8);
}

.footer-col {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.footer-tagline {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 500;
  color: var(--text-primary);
  margin-bottom: var(--space-2);
}

.footer-blurb {
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--text-muted);
  max-width: 40ch;
}

.footer-heading {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--silver);
  margin-bottom: var(--space-2);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--border-subtle);
}

.footer-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.footer-list li {
  font-size: var(--text-sm);
  line-height: 1.4;
}

.footer-list a {
  color: var(--text-body);
  transition: color var(--duration-fast) var(--ease-out);
}

.footer-list a:hover {
  color: var(--red);
}

/* The ↗ arrow on external links inherits silver-dim, brightens on hover */
.footer-list a span {
  color: var(--silver-dim);
  font-size: 0.85em;
  margin-left: 2px;
  transition: color var(--duration-fast) var(--ease-out);
}

.footer-list a:hover span {
  color: var(--red);
}

/* SOCIAL ICONS — small horizontal row of platform glyphs.
   Each icon is an inline SVG inheriting `currentColor`, so the
   color transition is just on the parent <a>. */
.footer-socials {
  list-style: none;
  padding: 0;
  margin: var(--space-4) 0 0;
  display: flex;
  gap: var(--space-3);
}

.footer-socials a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  color: var(--silver);
  transition: all var(--duration-fast) var(--ease-out);
}

.footer-socials a:hover {
  background: var(--red);
  border-color: var(--red);
  color: var(--bg-primary);
  transform: translateY(-2px);
}

/* ----- BOTTOM BAR ----- */

.footer-bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-4);
  padding-top: var(--space-6);
  border-top: 1px solid var(--border-subtle);
}

.footer-meta {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.footer-resources {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.footer-resources a {
  color: var(--silver);
  transition: color var(--duration-fast) var(--ease-out);
}

.footer-resources a:hover {
  color: var(--red);
}


/* ============================================================================
   12. ANIMATIONS
   ============================================================================ */

/* Live status dot — radiating pulse. The box-shadow expands and fades.
   Only runs when .live class is added to .status-dot. */
@keyframes pulse-live {
  0%   { box-shadow: 0 0 0 0    var(--red-glow); }
  70%  { box-shadow: 0 0 0 12px transparent; }
  100% { box-shadow: 0 0 0 0    transparent; }
}

/* About section backlight — animates `background-position` so the
   gradient appears to drift back and forth across the blurred halo,
   producing a slow ambient color cycle. Used by .about-photo-wrap. */
@keyframes about-glow {
  0%   { background-position:   0% 50%; }
  50%  { background-position: 100% 50%; }
  100% { background-position:   0% 50%; }
}

/* Tutorial card skeleton — shimmer effect while data is being fetched. */
@keyframes tutorial-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* Lightbox fade-in when modal opens. */
@keyframes lightbox-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Respect users who've turned on "reduce motion" in their OS settings.
   Some people get migraines or motion sickness from animated backgrounds.
   We freeze the glow at a fixed gradient position rather than removing
   it entirely — they still get the color, just no movement. */
@media (prefers-reduced-motion: reduce) {
  .about-photo-wrap::before {
    animation: none;
    background-position: 50% 50%;
  }
  .status-dot.live {
    animation: none;
  }
  .tutorial-skeleton {
    animation: none;
  }
}


/* ============================================================================
   13. RESPONSIVE
   ============================================================================
   Tablet breakpoint at 1024px, mobile breakpoint at 640px.
   Mobile-first thinking would flip these — we'd start narrow and add
   styles at wider breakpoints. Desktop-first (what we're doing) starts
   wide and overrides for smaller screens. Either approach is fine;
   desktop-first is easier to read top-to-bottom for learning.
   ============================================================================ */

/* Tablet and below */
@media (max-width: 1024px) {

  .nav-container,
  .hero-container,
  .section-container,
  .footer-container {
    padding-left: var(--space-6);
    padding-right: var(--space-6);
  }

  /* Drop the hero headline line breaks — let the text reflow.
     The <br> tags are still in the HTML but get hidden by display:none. */
  .hero-headline br {
    display: none;
  }

  /* Dashboard collapses from 4-up to 2-up */
  .dashboard {
    grid-template-columns: repeat(2, 1fr);
  }

  /* Watermark gets smaller and slightly dimmer so it doesn't overwhelm
     the smaller viewport. */
  .hero-watermark {
    width: min(60vh, 480px);
    height: min(60vh, 480px);
    right: -20%;
    opacity: 0.10;
  }

  /* About watermark — same scaling treatment as the hero. */
  .about-watermark {
    width: min(50vh, 400px);
    height: min(50vh, 400px);
    left: -25%;
    opacity: 0.08;
  }

  /* About section — collapse to single column on tablet, photo first.
     Drop the negative-margin photo offset and the pull quote bleed
     since both only make sense in the two-column layout. */
  .about-grid {
    grid-template-columns: 1fr;
    gap: var(--space-12);
  }

  .about-photo-col {
    order: -1;          /* photo above text on mobile/tablet */
    margin-top: 0;
    max-width: 480px;   /* don't let photo dominate full width */
  }

  .about-pullquote {
    margin-right: 0;    /* no bleed when there's no second column */
  }

  /* Credentials become two-up on tablet to use the wider single column. */
  .about-credentials {
    grid-template-columns: repeat(3, 1fr);
  }

  /* Build section — services and tools both stay 2-up on tablet
     (they were 2-up on desktop too). The titles get a touch tighter. */
  .build-title {
    margin-bottom: var(--space-3);
  }

  .build-title br {
    display: none;
  }

  /* Tools grid collapses from 4-up to 2-up on tablet so cards don't
     get too narrow to be readable. */
  .tools-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  /* Tutorials grid same treatment — 4 cards becomes 2×2. */
  .tutorials-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .tutorials-title br {
    display: none;
  }

  /* Live panel — info on top, stage below on tablet (the embed needs
     enough width to be useful). */
  .live-panel {
    grid-template-columns: 1fr;
  }

  .live-panel-stage {
    /* Maintain 16:9 ratio when stacked, so the embed is properly sized. */
    aspect-ratio: 16 / 9;
    min-height: 0;
  }

  .live-title br,
  .standards-headline br {
    display: none;
  }

  .standards-banner {
    padding: var(--space-6) var(--space-8);
  }

  .values-title br {
    display: none;
  }

  /* Tier grid — three columns becomes one column on tablet so each
     card has room to breathe. The popular card loses its elevation
     since elevation only makes sense in a row context. */
  .tier-grid {
    grid-template-columns: 1fr;
    max-width: 480px;
    margin: 0 auto;
  }

  .tier-popular {
    transform: none;
  }

  .tier-popular:hover {
    transform: translateY(-2px);
  }

  .join-title br {
    display: none;
  }

  /* Footer — 4 columns becomes a 2×2 grid on tablet. The brand column
     spans both columns of the top row so it gets full width. */
  .footer-grid {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-6);
  }

  .footer-col-brand {
    grid-column: 1 / -1;
  }

  /* ----- ABOUT PAGE ----- */

  .page-hero-title br {
    display: none;
  }

  .story-grid {
    grid-template-columns: 1fr;
    gap: var(--space-12);
  }

  .story-photo-col {
    order: -1;          /* photo above prose on tablet/mobile */
    margin-top: 0;
    max-width: 320px;   /* keep the same cap when stacked */
    margin-left: 0;     /* hug the left when stacked, not centered */
    /* Sticky doesn't make sense once the column is stacked above
       the prose — it would just pin to the top forever. Disable it. */
    position: static;
  }

  .story-title br {
    display: none;
  }

  .principles-grid,
  .connect-grid {
    grid-template-columns: 1fr;
  }

  .now-block {
    padding: var(--space-6) var(--space-8);
  }

  /* Affiliates page — partners and clients grids collapse to single column */
  .partners-grid,
  .clients-grid {
    grid-template-columns: 1fr;
  }

  .partners-title br {
    display: none;
  }

  .partner-cta-block {
    padding: var(--space-6) var(--space-8);
  }

  /* Recommendations page — 3 columns to 2 on tablet */
  .recs-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  /* Portfolio page — carousel adjusts proportions, more-work grid
     drops from 4 to 2 columns, thumb strip stays at 4 (small enough). */
  .featured-carousel-wrap {
    height: clamp(420px, 70vw, 600px);
  }

  .featured-slide {
    width: 180px;
    height: 280px;
  }

  .featured-slide:nth-child(3) {
    left: 55%;
  }

  .featured-slide:nth-child(4) {
    left: calc(55% + 200px);
  }

  .featured-slide:nth-child(5) {
    left: calc(55% + 400px);
  }

  .featured-slide:nth-child(n+6) {
    left: calc(55% + 600px);
    opacity: 0;
  }

  .featured-slide-content {
    bottom: var(--space-8);
    left: var(--space-8);
    right: var(--space-8);
  }

  .work-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  /* Community page — people grid drops to 2 columns on tablet */
  .people-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  /* Creators carousel on tablet — slightly smaller previews so they fit
     comfortably in narrower viewports. */
  .creators-carousel-wrap {
    height: clamp(420px, 65vw, 520px);
  }

  .creator-slide {
    width: 160px;
    height: 240px;
  }

  .creator-slide:nth-child(2) {
    left: 58%;
  }

  .creator-slide:nth-child(3) {
    left: calc(58% + 175px);
  }

  .creator-slide:nth-child(n+4) {
    left: calc(58% + 350px);
    opacity: 0;
  }

  .creator-slide-content {
    bottom: var(--space-6);
    left: var(--space-6);
    right: var(--space-6);
  }
}

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

  /* Hide non-essential nav items, keep only the store CTA visible.
     A future iteration can add a hamburger menu for the rest. */
  .nav-menu li:not(:last-child) {
    display: none;
  }

  .hero {
    padding-top: calc(var(--nav-height) + var(--space-8));
  }

  .hero-cta {
    flex-direction: column;
    align-items: stretch;
  }

  .cta {
    justify-content: space-between;
  }

  .dashboard {
    grid-template-columns: 1fr;
  }

  .section {
    padding: var(--space-16) 0;
  }

  /* Hide the watermark entirely on mobile — at this width it would either
     dominate or just look like a noisy texture. The brand name in the nav
     is enough on small screens. */
  .hero-watermark,
  .about-watermark {
    display: none;
  }

  /* About section — stack credentials on mobile, scale down headline. */
  .about-credentials {
    grid-template-columns: 1fr;
  }

  .about-pullquote {
    font-size: var(--text-xl);
    padding: var(--space-3) var(--space-4);
  }

  /* Build section — collapse both grids to single column on phone. */
  .services-grid,
  .tools-grid,
  .tutorials-grid,
  .community-grid,
  .resources-grid,
  .tier-grid {
    grid-template-columns: 1fr;
  }

  .tools-header {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-2);
  }

  /* Lightbox — reduce padding so the video gets more room on small screens. */
  .lightbox {
    padding: var(--space-4);
  }

  .lightbox-close {
    top: var(--space-3);
    right: var(--space-3);
    width: 36px;
    height: 36px;
    font-size: 24px;
  }

  /* Live & Community mobile tweaks */
  .standards-banner {
    padding: var(--space-6);
  }

  .ww-badge,
  .network-badge {
    min-height: 160px;
  }

  .ww-badge img,
  .network-badge img {
    max-height: 160px;
  }

  /* Footer collapses to single column on mobile. */
  .footer-grid {
    grid-template-columns: 1fr;
    gap: var(--space-8);
  }

  .footer-col-brand {
    grid-column: auto;
  }

  .footer-bottom {
    flex-direction: column;
    align-items: flex-start;
    text-align: left;
  }

  /* About page mobile tweaks */
  .now-block {
    padding: var(--space-6);
  }

  .timeline {
    padding-left: var(--space-6);
  }

  .timeline-dot {
    left: calc(-1 * var(--space-6) - 5px);
  }

  /* Affiliates page mobile */
  .partner-cta-block {
    padding: var(--space-6);
  }

  .partner-logo {
    height: 100px;
  }

  .partner-code {
    padding: var(--space-2) var(--space-3);
  }

  /* Recommendations page mobile — single column for cards */
  .recs-grid {
    grid-template-columns: 1fr;
  }

  .recs-quicknav {
    gap: var(--space-1);
  }

  .recs-disclosure,
  .recs-attribution {
    padding: var(--space-3) var(--space-4);
  }

  /* Portfolio page mobile */
  .work-grid {
    grid-template-columns: 1fr;
  }

  .work-filters {
    gap: var(--space-1);
  }

  .work-filter {
    padding: var(--space-2) var(--space-3);
  }

  /* Carousel mobile — even smaller stacked slides on the right,
     content text scales down. */
  .featured-carousel-wrap {
    height: clamp(380px, 90vw, 500px);
  }

  .featured-slide {
    width: 140px;
    height: 220px;
  }

  .featured-slide:nth-child(3) {
    left: 55%;
  }

  .featured-slide:nth-child(4) {
    left: calc(55% + 160px);
  }

  .featured-slide:nth-child(5) {
    left: calc(55% + 320px);
  }

  .featured-slide:nth-child(n+6) {
    left: calc(55% + 480px);
    opacity: 0;
  }

  .featured-slide-content {
    bottom: var(--space-6);
    left: var(--space-6);
    right: var(--space-6);
  }

  .featured-meta {
    gap: var(--space-1) var(--space-3);
  }

  .carousel-nav {
    bottom: var(--space-3);
    right: var(--space-3);
  }

  .carousel-btn {
    width: 36px;
    height: 36px;
  }

  /* Thumb strip on mobile — stays as a 4-column grid but with
     much shorter names allowed. */
  .thumb-strip {
    gap: var(--space-2);
  }

  .thumb-jump-name {
    font-size: 9px;
  }

  /* Community page mobile */
  .people-grid {
    grid-template-columns: 1fr;
  }

  /* Creators carousel on mobile — even smaller previews, content text
     scales down, nav buttons stay in their absolute position. */
  .creators-carousel-wrap {
    height: clamp(380px, 90vw, 480px);
  }

  .creator-slide {
    width: 120px;
    height: 200px;
  }

  .creator-slide:nth-child(2) {
    left: 58%;
  }

  .creator-slide:nth-child(3) {
    left: calc(58% + 135px);
  }

  .creator-slide:nth-child(n+4) {
    left: calc(58% + 270px);
    opacity: 0;
  }

  .creator-slide-content {
    bottom: var(--space-4);
    left: var(--space-4);
    right: var(--space-4);
  }

  .creator-slide-header {
    gap: var(--space-3);
  }

  .creator-slide-avatar {
    width: 56px;
    height: 56px;
  }

  .creators-carousel-wrap .carousel-nav {
    bottom: var(--space-3);
    right: var(--space-3);
  }

  .creators-counter {
    top: var(--space-2);
    right: var(--space-2);
  }

  .subs-grid {
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  }

  /* Fourthwall members on mobile — slightly smaller cards & images */
  .members-grid {
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  }

  .member-tier-image {
    width: 90px;
    height: 90px;
  }

  .coming-soon-block {
    padding: var(--space-8) var(--space-6);
  }
}
