/* ============================================
   V3 PROJECT COLUMNS - RESPONSIVE STYLES
   Phase 8A-B2 Production Port (2026-03-03)

   Rewritten to align with north star DOM (iframe-project-columns-v8-production.html).
   Previous version contained orphaned selectors from earlier Phase 8 testing round
   (.project-cell, .project-title-collapsed, [data-collapsed-state], [data-info-variation="2"])
   that matched neither production HTML nor north star iframe — archived in git history.

   Responsive blocks ported:
   B1: Active-collapsed short screen (max-height: 720px)
   B2: Timeline endpoint vertical labels (max-width: 767px)
   B3: Info compact timeline vertical (max-width: 599px)
   B4: Info panel min-height (max-width: 599px)
   B5: COMPACT height tier (max-height: 699px)
   B6: STANDARD height tier (700-799px)
   B7: COMFORTABLE height tier (min-height: 800px)

   NOTE: Targets north star DOM classes — will fully activate when base f.e code is ported.
   Overview-specific responsive blocks (B8, B9) are in v3-overview-overlay.css.

   Import order (in index.html):
   1. project-column-styles.css (base styles)
   2. v3-project-columns-responsive.css (this file - responsive overrides)
   ============================================ */

/* START CLEAN-FIX-PHASE8-RESPONSIVE-PRODUCTION */

/* ============================================
   UNIVERSAL CSS VARIABLES
   Reserved header/footer space for mobile viewports
   ============================================ */

/* START CLEAN-FIX-8A-B2-PROJCOL-PORT — Universal :root responsive variables
   Ported from iframe-project-columns-v8-production.html
   Provides reserved header/footer space calculations for mobile layout
   To revert: Delete between START/END CLEAN-FIX-8A-B2-PROJCOL-PORT markers */

/* ----------------------------------------
   XS/SM Breakpoint: Mobile reserved space + responsive font sizes
   ---------------------------------------- */
@media (max-width: 767px) {
    :root {
        --reserved-header: 60px;   /* 10×6n - mobile default */
        --reserved-footer: 48px;   /* 8×6n - mobile default */
        --available-height: calc(100vh - var(--reserved-header) - var(--reserved-footer));
        /* B1 short-screen responsive font sizes (6n compliant) */
        --font-size-r-number-short: 3.375rem;  /* 54px = 9×6n, reduced from super-huge (72px) for short screens */
        --font-size-r-title-short: 1.875rem;   /* 30px = 5×6n, reduced from huge (48px) for short screens */
    }
}

/* ----------------------------------------
   MD Breakpoint: Tablet reserved space
   ---------------------------------------- */
@media (min-width: 768px) and (max-width: 819px) {
    :root {
        --reserved-header: 66px;  /* 11×6n - tablet */
        --reserved-footer: 54px;  /* 9×6n - tablet */
    }
}

/* END CLEAN-FIX-8A-B2-PROJCOL-PORT — Universal :root responsive variables */


/* ============================================
   B1: ACTIVE-COLLAPSED SHORT SCREEN RESPONSIVE
   Ported from: CLEAN-FIX-V8-AC-SHORT-SCREEN-RESPONSIVE (lines 1057-1089)
   Target: Screens ≤720px height (iPhone SE portrait 667px, etc.)
   Problem: On short screens, header copy too large relative to alive-preview
   Solution: Reduce typography and container sizes proportionally
   6n Compliance: 54px (9×6n), 30px (5×6n), 114px (19×6n)
   NOTE: Targets north star DOM classes — will activate when base f.e code is ported
   ============================================ */

/* B1 short-screen block MOVED to after Step 1c — see CLEAN-FIX-C8-P2B-F05-CASCADE-BORDERS below.
   Cascade fix: on iPhone SE (375×667), @media max-height:720px MUST come AFTER @media max-width:991px
   so that short-screen overrides (54px/30px/114px) win over main block values (72px/48px/200px). */

/* ============================================
   B2: TIMELINE ENDPOINT VERTICAL LABELS
   Ported from: CLEAN-FIX-V8-G6-ENDPOINT-VERTICAL-PHONE (lines 2340-2392)
   Target: XS + SM viewports (<768px)
   Problem: Endpoint labels collide with phase labels at 375px
   Solution: Stack prefix/value vertically, center-align with nodes
   6n Fix: Endpoint nodes 21px → 18px (3×6n)
   NOTE: Targets north star DOM classes — will activate when base f.e code is ported
   ============================================ */

/* START CLEAN-FIX-8A-B2-PROJCOL-PORT — B2 Timeline endpoint vertical
   Ported from iframe-project-columns-v8-production.html (CLEAN-FIX-V8-G6-ENDPOINT-VERTICAL-PHONE)
   6n fix applied: endpoint node positioning 21px → 18px (3×6n)
   To revert: Delete between START/END CLEAN-FIX-8A-B2-PROJCOL-PORT markers */

@media (max-width: 767px) {
    /* Hide original horizontal labels at phone sizes */
    .inline-timeline .timeline-bar-endpoint-label {
        display: none;
    }

    /* Vertical endpoint prefix (above node) - e.g., "wk" */
    /* G6 FINAL: font-weight 300 for visual hierarchy (UI-Ninja: design token compliant) */
    .timeline-bar-endpoint-prefix {
        position: absolute;
        top: 6px;
        font-family: var(--font-primary);
        font-size: var(--font-size-specialized);
        font-weight: 300; /* G6: Lighter weight for hierarchy */
        color: var(--warm);
        text-transform: lowercase;
        white-space: nowrap;
        line-height: 1;
    }

    /* Vertical endpoint value (below node) - e.g., "0" or "5" */
    .timeline-bar-endpoint-value {
        position: absolute;
        bottom: 6px;
        font-family: var(--font-primary);
        font-size: var(--font-size-specialized);
        font-weight: 400; /* G6: Regular weight for hierarchy contrast */
        color: var(--warm);
        text-transform: lowercase;
        white-space: nowrap;
        line-height: 1;
    }

    /* Start endpoint positioning (left side) - CENTER ALIGNED */
    .inline-timeline .timeline-bar-endpoint-prefix.start,
    .inline-timeline .timeline-bar-endpoint-value.start {
        left: 18px;  /* 3×6n (was 21px in north star — 6n fix applied) */
        transform: translateX(-50%);
        padding-left: 6px; /* Edge clearance */
    }

    /* End endpoint positioning (right side) - CENTER ALIGNED */
    .inline-timeline .timeline-bar-endpoint-prefix.end,
    .inline-timeline .timeline-bar-endpoint-value.end {
        right: 18px;  /* 3×6n (was 21px in north star — 6n fix applied) */
        transform: translateX(50%);
        padding-right: 6px; /* Edge clearance */
    }

    /* Endpoint nodes: aligned with padded labels */
    .timeline-bar-endpoint-node.start { left: 18px; }   /* 3×6n (was 21px — 6n fix) */
    .timeline-bar-endpoint-node.end { right: 18px; }     /* 3×6n (was 21px — 6n fix) */
}

/* END CLEAN-FIX-8A-B2-PROJCOL-PORT — B2 Timeline endpoint vertical */


/* ============================================
   B3 + B4: INFO PANEL MOBILE RESPONSIVE
   B3: Info compact timeline vertical layout (max-width: 599px)
   B4: Info panel min-height spread (max-width: 599px)
   Ported from: CLEAN-FIX-PHASE8-V6A-INFO-LABELS (lines 3871-3942)
   6n Note: left: 9px is geometric centering of 6px diamond, acceptable
   6n Fix: min-height calc(100vh - 200px) → calc(100vh - 198px) (33×6n)
   NOTE: Targets north star DOM classes — will activate when base f.e code is ported
   ============================================ */

/* START CLEAN-FIX-8A-B2-PROJCOL-PORT — B3 Info compact timeline vertical + B4 Info panel min-height
   Ported from iframe-project-columns-v8-production.html (CLEAN-FIX-PHASE8-V6A-INFO-LABELS)
   6n fix applied: min-height calc 200px → 198px (33×6n)
   To revert: Delete between START/END CLEAN-FIX-8A-B2-PROJCOL-PORT markers */

/* B3: Vertical Timeline for Mobile (XS) */
@media (max-width: 599px) {
    .info-compact-timeline {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--spacing-12);
        padding: var(--spacing-12) 0;
    }

    .info-compact-timeline span {
        display: flex;
        align-items: center;
        gap: var(--spacing-6);
    }

    /* Diamond marker before each timeline point */
    .info-compact-timeline span::before {
        content: '';
        width: 6px;
        height: 6px;
        background: var(--current-accent);
        transform: rotate(45deg);
        flex-shrink: 0;
    }

    /* Hide the arrow in vertical mode */
    .info-compact-timeline .timeline-arrow {
        display: none;
    }

    /* Add vertical line connecting timeline points */
    .info-compact-timeline {
        position: relative;
        padding-left: var(--spacing-18);
    }

    .info-compact-timeline::after {
        content: '';
        position: absolute;
        left: 9px; /* Center of 6px diamond — geometric centering, acceptable */
        top: calc(var(--spacing-12) + 3px);
        bottom: calc(var(--spacing-12) + 3px);
        width: 1px;
        background: var(--light);
    }
}

/* B4: Spread content vertically on XS screens */
@media (max-width: 599px) {
    .info-panel {
        justify-content: space-between;
        min-height: calc(100vh - 198px); /* 33×6n (was 200px — 6n fix) — account for header, tabs, footer */
    }
}

/* END CLEAN-FIX-8A-B2-PROJCOL-PORT — B3 + B4 Info panel mobile */


/* ============================================
   B5 + B6 + B7: HEIGHT-RESPONSIVE SPACING TIERS
   Ported from: CLEAN-FIX-V8-G7-RESPONSIVE-SPACING (lines 4307-4414)
   Three tiers based on viewport height:
     COMPACT (<700px): Minimize padding for max stream space
     STANDARD (700-799px): Medium padding for balance
     COMFORTABLE (≥800px): Full padding for generous layout
   6n Compliance: All values 6n-compliant
   6n Notes: 3px margin (micro-spacing <6px, acceptable), 9px padding (1.5×6n, user decision)
   NOTE: Targets north star DOM classes — will activate when base f.e code is ported
   ============================================ */

/* START CLEAN-FIX-8A-B2-PROJCOL-PORT — B5+B6+B7 Height-tier responsive spacing
   Ported from iframe-project-columns-v8-production.html (CLEAN-FIX-V8-G7-RESPONSIVE-SPACING)
   To revert: Delete between START/END CLEAN-FIX-8A-B2-PROJCOL-PORT markers */

/* === B5: COMPACT — Shortest screens (<700px height, e.g., iPhone SE) === */
/* Minimize padding to give stream maximum vertical space */
@media (max-height: 699px) {
    .info-layout-content {
        padding: 12px 12px 12px 36px; /* Reduced: 2×6n sides, 6×6n left for baseline */
    }

    .info-layout-content::before {
        left: 18px; /* Adjusted baseline for 36px padding */
        top: 12px;
        bottom: 12px;
    }

    .info-lv-subtitle,
    .info-lv-impact,
    .info-lv-tags {
        padding-top: 6px; padding-bottom: 6px; /* 1×6n vertical — preserves padding-left */
    }

    /* Adjust notch positions for reduced padding */
    .notch-node {
        left: -18px; /* 36px - 18px baseline = 18px */
    }

    .info-lv-impact .notch-node {
        left: -24px; /* 18px + 6px border */
    }

    .info-element-divider {
        margin: 3px 0; /* Reduced: 0.5×6n micro-spacing */
    }

    /* CLEAN-FIX-C8-VR-INFO-STREAM: B5 tile min-height */
    .info-layout-tile { min-height: 240px; }          /* 40×6n — compact */

    /* Stream: min-height only, flex:1 fills remaining space */
    .fe-info-stream-container {
        min-height: 60px; /* 10×6n - minimum viable */
    }
}

/* === B6: STANDARD — Medium height screens (700-799px, e.g., iPhone 14) === */
@media (min-height: 700px) and (max-height: 799px) {
    .info-layout-content {
        padding: 18px 18px 18px 42px; /* Medium: 3×6n sides, 7×6n left */
    }

    .info-layout-content::before {
        left: 24px; /* Standard baseline */
        top: 18px;
        bottom: 18px;
    }

    .info-lv-subtitle,
    .info-lv-impact,
    .info-lv-tags {
        padding-top: 9px; padding-bottom: 9px; /* 1.5×6n vertical — preserves padding-left */
    }

    /* Standard notch positions */
    .notch-node {
        left: -18px;
    }

    .info-lv-impact .notch-node {
        left: -24px;
    }

    .info-element-divider {
        margin: 6px 0; /* Standard: 1×6n */
    }

    /* CLEAN-FIX-C8-VR-INFO-STREAM: B6 tile min-height */
    .info-layout-tile { min-height: 270px; }          /* 45×6n — standard */

    /* Stream: min-height only, flex:1 fills remaining space */
    .fe-info-stream-container {
        min-height: 72px; /* 12×6n */
    }
}

/* === B7: COMFORTABLE — Taller screens (≥800px height) === */
@media (min-height: 800px) {
    .info-layout-content {
        padding: 24px 24px 24px 42px; /* Full: 4×6n sides, 7×6n left */
    }

    .info-layout-content::before {
        left: 24px;
        top: 24px;
        bottom: 24px;
    }

    .info-lv-subtitle,
    .info-lv-impact,
    .info-lv-tags {
        padding-top: 12px; padding-bottom: 12px; /* 2×6n vertical — preserves padding-left */
    }

    .notch-node {
        left: -18px;
    }

    .info-lv-impact .notch-node {
        left: -24px;
    }

    .info-element-divider {
        margin: 6px 0; /* Standard: 1×6n */
    }

    /* CLEAN-FIX-C8-VR-INFO-STREAM: B7 tile min-height */
    .info-layout-tile { min-height: 300px; }          /* 50×6n — comfortable (matches north star) */

    /* Stream: min-height only, flex:1 fills remaining space */
    .fe-info-stream-container {
        min-height: 90px; /* 15×6n */
    }
}

/* END CLEAN-FIX-8A-B2-PROJCOL-PORT — B5+B6+B7 Height-tier spacing */


/* END CLEAN-FIX-PHASE8-RESPONSIVE-PRODUCTION */


/* ============================================
   C8–C11 PHASE 1: TOC + d.c + a.c RESPONSIVE PORT
   Phase 8A-B.8 C8–C11 (2026-03-27)
   Fresh approach after previous Layer A+B attempt reverted to 552276b.
   Ports from north star: iframe-project-columns-v8-production.html
   Sub-phase strategy: 1a container → 1b d.c → 1c a.c → 1d TOC → 1e-1g JS
   ============================================ */


/* ============================================
   STEP 1a: CONTAINER OVERRIDE + CSS VARIABLES + DESKTOP GUARD
   START CLEAN-FIX-C8-P1A-CONTAINER-OVERRIDE

   LOAD-BEARING: This block MUST appear in v3-project-columns-responsive.css which loads
   AFTER project-column-styles.css (index.html link order: base at line ~27, responsive at line ~31).
   Source order is what makes this override work — the 991px rules here override the 767px
   rules in project-column-styles.css (lines 722-734) because both match at mobile widths
   and later source order wins. If CSS import order changes, mobile layout WILL break.

   This is the CRITICAL fix that was missing in the first attempt. Without this override,
   the 767px flex-direction:column rule stacks columns vertically — the #1 root cause
   of the previous round failure.

   Ported from: iframe-project-columns-v8-production.html lines 354-395
   To revert: Search CLEAN-FIX-C8-P1A-CONTAINER-OVERRIDE and delete between START/END markers
   ============================================ */

/* --- Desktop guard: hide mobile-only elements at ≥820px (shifted from 992px in P5-S3) --- */
@media (min-width: 820px) {
    .alive-content,
    #tocContainer,
    .instruction-bar {
        display: none;
    }
}

/* --- Mobile container + column override (≤819px, shifted from 991px in P5-S3) --- */
@media (max-width: 819px) {

    /* CSS variables for d.c/a.c layout (extends existing --reserved-header/footer) */
    :root {
        /* d.c (default-collapsed) layout */
        --default-collapsed-width: 18px;        /* 3×6n — skinny column width */

        /* TOC bar dimensions */
        --va-toc-height: 54px;                  /* 9×6n — bottom navigation bar */
        --va-toc-item-size: 36px;               /* 6×6n — touch target per diamond */
        --va-toc-indicator-size: 24px;           /* 4×6n — diamond indicator visual size */
        --va-toc-gap: 12px;                     /* 2×6n — gap between TOC items */

        /* Instruction bar */
        --instruction-bar-height: 48px;          /* 8×6n — "DRAG: explore | LIFT: view" bar */

        /* Reserved space for TOC */
        --reserved-toc: var(--va-toc-height);

        /* Concrete easing — asymmetric "slab" transitions (from iframe G12)
           Crane Lift: slow departure, decisive arrival (expand direction)
           Counterweight: snappy departure, cushioned arrival (collapse direction)
           Duration: 480ms (80×6n) — heavier than default 400ms for physical weight */
        --va-ease-concrete-expand: cubic-bezier(0.22, 0.80, 0.36, 1.0);
        --va-ease-concrete-collapse: cubic-bezier(0.38, 0.0, 0.22, 1.0);
        --transition-concrete: 480ms;

        /* Stagger timing for d.c → a.c transition choreography */
        --va-stagger-base: 80ms;

        /* Current project accent (set by JS on state change) */
        --current-accent: var(--warm);

        /* Easing curves for state transitions (north star lines 157-158) */
        --va-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
        --va-ease-spring: cubic-bezier(0.34, 1.2, 0.64, 1);
    }

    /* --- Container override: horizontal flex + fixed positioning ---
       Overrides project-column-styles.css lines 166-173 (base) and 722-727 (767px breakpoint).
       At viewports ≤767px, BOTH the 767px rules and these 991px rules match.
       These rules win via source order (this file loads after base file). */
    .projects-container {
        flex-direction: row;                    /* Override 767px column → row */
        width: 100%;                            /* Override 96% → full viewport */
        margin: 0;                              /* Override 2% margins */
        position: fixed;                        /* Match iframe: fixed within reserved space */
        top: calc(var(--reserved-header) + var(--instruction-bar-height, 48px)); /* Below header + instruction bar */
        bottom: calc(var(--reserved-footer) + var(--reserved-toc) + var(--spacing-12, 12px));
        left: 0;
        right: 0;
        height: auto;                           /* Override calc() height — top/bottom define height */
        z-index: 10;                            /* Above page content, below header/footer/TOC */
        overflow: hidden;                       /* Match iframe — clips columns at edge */
    }

    /* --- Column override: d.c SKINNY is the DEFAULT mobile state ---
       All columns start as skinny 18px strips at mobile. The .active-collapsed class
       (step 1c) overrides ONE column to the hero layout. This approach makes the d.c
       state visible immediately without JS — testable at every step.
       Overrides project-column-styles.css lines 178-199 (base) and 729-734 (767px breakpoint).
       Ported from: iframe lines 768-782 (.project-column.default-collapsed) */
    .project-column {
        flex: none;                             /* Override base flex:0.8 + 767px flex:none (same value, explicit) */
        width: var(--default-collapsed-width);  /* 18px (3×6n) — skinny column */
        min-width: 12px;                        /* 2×6n minimum */
        max-width: 24px;                        /* 4×6n maximum */
        height: 100%;                           /* Override 767px height:100vh */
        background: var(--light);
        padding: var(--spacing-6, 6px);
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        align-items: stretch;
        overflow: hidden;
        clip-path: polygon(2% 0, 98% 0, 100% 100%, 0% 100%); /* Match iframe */
        margin: 0;
        --half-box-size: 12px;                  /* 2×6n — compact coord point */
    }

    /* --- Hide alive-content by default at mobile ---
       Shown only when .active-collapsed is applied (step 1c override: display: grid).
       Without this, alive-content bleeds into skinny d.c columns. */
    .alive-content {
        display: none;
    }

    /* --- LOAD-BEARING: Hide desktop expanded content at mobile ---
       This rule prevents the .project-expanded div (hundreds of lines of desktop content)
       from competing for layout space inside each column. This was the #2 root cause of
       the first round failure. The iframe has no .project-expanded equivalent. */
    .project-column .project-expanded,
    .project-column.active .project-expanded {
        display: none;
    }

    /* --- Hide navigation instructions at mobile (matches existing 767px rule) --- */
    .navigation-instructions {
        display: none;
    }

} /* END @media (max-width: 819px) — Step 1a */

/* --- Anticipation animation classes (not breakpoint-scoped — only applied by mobile JS) ---
   3-phase choreography: Inhale (scaleX 0.98, 60ms) → Release (scaleX 1, 60ms) → Flex
   transition-property: transform prevents clobbering flex/clip-path transitions.
   Ported from: iframe lines 398-422 */
.project-column.col-anticipate {
    transform: scaleX(0.98);
    transition-property: transform;
    transition-duration: 60ms;
    transition-timing-function: cubic-bezier(0.38, 0.0, 0.22, 1.0);
}
.project-column.col-anticipate-release {
    transform: scaleX(1);
    transition-property: transform;
    transition-duration: 60ms;
    transition-timing-function: ease-out;
}

/* Concrete collapse easing override (applied by JS before class toggle) */
.project-column.concrete-collapse {
    transition: flex var(--transition-concrete, 480ms) var(--va-ease-concrete-collapse, cubic-bezier(0.38, 0.0, 0.22, 1.0)),
                background 0.3s ease,
                clip-path var(--transition-concrete, 480ms) var(--va-ease-concrete-collapse, cubic-bezier(0.38, 0.0, 0.22, 1.0));
}

@media (prefers-reduced-motion: reduce) {
    .project-column.col-anticipate,
    .project-column.col-anticipate-release {
        transform: none;
        transition: none;
    }
}

/* END CLEAN-FIX-C8-P1A-CONTAINER-OVERRIDE */


/* ============================================
   STEP 1b: DEFAULT-COLLAPSED (d.c) INNER CONTENT STYLING
   START CLEAN-FIX-C8-P1B-DC-SKINNY
   Ported from: iframe-project-columns-v8-production.html lines 785-904
   The d.c COLUMN dimensions (18px, flex:none) are now the DEFAULT mobile state
   in step 1a's .project-column rule above. This step styles the CONTENT inside
   those skinny columns: vertical text, L-shape coords, project number positioning.
   Production adaptation: targets .project-collapsed (not iframe's .collapsed-content)
   and handles .project-title-container wrapper (not in iframe).
   To revert: Search CLEAN-FIX-C8-P1B-DC-SKINNY and delete between START/END markers
   ============================================ */

@media (max-width: 819px) {

    /* --- d.c Collapsed Content Layout ---
       Production uses .project-collapsed (iframe uses .collapsed-content).
       Ported from: iframe lines 785-796 */
    .project-column .project-collapsed {
        opacity: 1;
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        align-items: flex-start;                /* Left-align for L-shape positioning */
        padding: 0;
        gap: var(--spacing-6, 6px);
        height: 100%;
        width: 100%;
        position: relative;                     /* Positioning context for project-number */
    }

    /* Production-specific: .project-title-container wrapper doesn't exist in iframe.
       display:contents removes wrapper from layout, children act as direct flex children. */
    .project-column .project-title-container {
        display: contents;
    }

    /* --- d.c Project Number (inside L-shape) ---
       Absolute positioned within coords-system.
       Ported from: iframe lines 806-815 */
    .project-column .project-number {
        position: absolute;
        top: 15px;                              /* Below horizontal line: 6px padding + 9px clearance */
        left: 6px;                              /* Right of vertical line */
        font-size: var(--font-size-small, 0.8rem);
        font-weight: 700;
        color: var(--current-accent);
        opacity: var(--opacity-default, 0.72);
        line-height: 1;
    }

    /* --- d.c Vertical Title ---
       Writing mode vertical, pushed to column bottom.
       Ported from: iframe lines 821-835 */
    .project-column .project-title {
        font-size: var(--font-size-small, 0.8rem);
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.5px;
        writing-mode: vertical-rl;
        text-orientation: mixed;
        color: var(--dark);
        opacity: 1;
        margin-top: auto;                       /* Push to bottom of column */
        padding-bottom: var(--spacing-6, 6px);
        order: 3;
        align-self: center;
    }

    /* --- d.c L-Shape Coordinate System ---
       Compact coords sized for 18px column. Scoped to NON-active columns
       to prevent d.c sizing (min-height:18px, margin-left:-4px) from bleeding
       into the a.c hero layout where coords-system needs to be much larger.
       Ported from: iframe lines 850-894 */
    .project-column:not(.active-collapsed) .coords-system {
        order: 0;
        width: 100%;
        height: auto;
        min-height: 18px;                       /* 3×6n — point + line overlap space */
        flex-shrink: 0;
        padding-top: var(--spacing-6, 6px);
        position: relative;
        margin-left: -4px;                      /* Pull into padding for tighter L-shape alignment */
    }

    .project-column:not(.active-collapsed) .coord-point {
        position: absolute;
        left: 0;
        top: var(--spacing-6, 6px);
        opacity: var(--opacity-strong, 0.5);
        z-index: 2;
        animation: none;                        /* No pulsating in d.c state */
    }

    .project-column:not(.active-collapsed) .coord-line {
        display: block;
        opacity: var(--opacity-strong, 0.5);
        position: absolute;
    }

    /* L-shape horizontal: extends RIGHT from coord-point center */
    .project-column:not(.active-collapsed) .coord-line.x {
        width: 12px;                            /* 2×6n horizontal */
        height: 1px;
        top: calc(var(--spacing-6, 6px) + 3px);
        left: 3px;
    }

    /* L-shape vertical: extends DOWN from coord-point center */
    .project-column:not(.active-collapsed) .coord-line.y {
        width: 1px;
        height: 24px;                           /* 4×6n vertical */
        top: calc(var(--spacing-6, 6px) + 3px);
        left: 3px;
    }

} /* END @media (max-width: 819px) — Step 1b */

/* END CLEAN-FIX-C8-P1B-DC-SKINNY */


/* ============================================
   STEP 1c: ACTIVE-COLLAPSED (a.c) HERO LAYOUT CSS
   START CLEAN-FIX-C8-P1C-ALIVE-CONTENT
   Ported from: iframe-project-columns-v8-production.html lines 921-1114
   State: a.c = one column expanded to hero view (number, title, preview image)
   Overrides the default skinny state from step 1a with flex:4.
   alive-content shown, project-collapsed hidden in a.c state.
   Short-screen responsive (max-height: 720px) already in B1 block (lines 80-112) — not duplicated.
   To revert: Search CLEAN-FIX-C8-P1C-ALIVE-CONTENT and delete between START/END markers
   ============================================ */

@media (max-width: 819px) {

    /* --- a.c Column Container ---
       Overrides the default d.c skinny state (step 1a) with flex:4 to fill viewport.
       Ported from: iframe lines 921-926 */
    .project-column.active-collapsed {
        flex: 4;
        width: auto;                            /* Override d.c width: 18px */
        min-width: unset;                       /* Override d.c min-width: 12px */
        max-width: unset;                       /* Override d.c max-width: 24px */
        background: var(--white);
        clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
        padding: 0;                             /* Override d.c padding: 6px */
    }

    /* --- a.c Child Visibility ---
       Hide project-collapsed (d.c content), show alive-content (a.c hero) */
    .project-column.active-collapsed .project-collapsed {
        opacity: 0;
        pointer-events: none;
        position: absolute;                     /* Remove from layout flow */
    }

    /* --- a.c Background Grid (subtle architectural reference) ---
       3×3 grid lines at 0.05 opacity.
       Ported from: iframe lines 938-949 */
    .project-column.active-collapsed .alive-content::before {
        content: '';
        position: absolute;
        inset: 0;
        background-image:
            linear-gradient(to right, var(--dark) 1px, transparent 1px),
            linear-gradient(to bottom, var(--dark) 1px, transparent 1px);
        background-size: 33.33% 33.33%;
        opacity: var(--opacity-minimal, 0.05);
        pointer-events: none;
        z-index: 0;
    }

    /* --- a.c alive-content Grid Layout ---
       2-row grid: auto header (row 1), 1fr preview (row 2).
       Ported from: iframe lines 960-974 */
    .project-column.active-collapsed .alive-content {
        opacity: 1;
        pointer-events: auto;
        display: grid;
        grid-template-columns: 1fr;
        grid-template-rows: auto 1fr;
        gap: var(--spacing-6, 6px);
        position: relative;
        height: 100%;
        min-height: 100%;
        padding: var(--spacing-18, 18px);       /* 3×6n inset from container edges (iframe base:446) */
        padding-bottom: 0;                      /* Override — preview fills to bottom edge (iframe:973) */
    }

    /* --- a.c alive-header (grid row 1) ---
       Ported from: iframe lines 680-684 (R6 gap fix + margin) */
    .project-column.active-collapsed .alive-header {
        position: relative;
        gap: 0;                                     /* Override base 6px gap (iframe:681) */
        margin-bottom: var(--spacing-6, 6px);       /* 1×6n gap below header (iframe:682) */
    }

    /* --- a.c coords-system — large frame for hero number/title ---
       START CLEAN-FIX-C8-P2B-F05-CASCADE-BORDERS — coords-system sizing
       To revert: restore min-height:150px, add padding:12px, remove margin-bottom + z-index */
    .project-column.active-collapsed .coords-system {
        position: relative;
        width: 100%;
        min-height: 200px;                      /* Match iframe:674 — number + gap + title + divider + headroom */
        margin-left: 0;                         /* Reset d.c -4px pull */
        margin-bottom: var(--spacing-12, 12px); /* 2×6n gap below L-frame (iframe:675) */
        z-index: 2;                             /* Above grid overlay ::before (iframe:673) */
        /* REMOVED: padding: var(--spacing-12) — iframe has NO a.c coords-system padding.
           Alive-number/title use absolute positioning from coords-system edge. */
    }

    /* --- a.c coord elements — compact L-shape frame (72px arms) ---
       North star L-shape: 72px horizontal, 72px vertical (iframe:695-701).
       Iframe has NO a.c opacity override — base 1.0 cascades.
       To revert: coord-line.x width→168px, coord-line.y height→100%, add opacity:0.5 */
    .project-column.active-collapsed .coord-point {
        position: absolute;
        left: 0;
        top: 0;
        opacity: 1;                             /* Full opacity in a.c (not dimmed like d.c) */
        z-index: 2;
    }

    .project-column.active-collapsed .coord-line {
        display: block;
        position: absolute;
        /* NO opacity override — iframe has none. Base 1.0 cascades correctly. */
    }

    .project-column.active-collapsed .coord-line.x {
        width: var(--spacing-72, 72px);         /* 12×6n — L-shape horizontal arm (iframe:696) */
        height: 1px;
        top: 3px;                               /* Center of coord-point */
        left: 3px;                              /* Start from coord-point center */
    }

    .project-column.active-collapsed .coord-line.y {
        width: 1px;
        height: var(--spacing-72, 72px);        /* 12×6n — L-shape vertical arm (iframe:700) */
        top: 3px;                               /* Start from coord-point center */
        left: 3px;                              /* Center of coord-point */
    }

    /* --- a.c alive-number — Super-huge project ID inside L-shape ---
       Ported from: iframe lines 996-1008 */
    .project-column.active-collapsed .alive-number {
        position: absolute;
        top: calc(3px + var(--spacing-12, 12px));
        left: calc(3px + var(--spacing-12, 12px));
        display: block;
        font-size: var(--font-size-super-huge, 4.5rem);  /* 72px (12×6n) */
        font-weight: 900;
        color: var(--current-accent);
        opacity: 1;
        line-height: 0.85;
        margin: 0;
        padding: 0;
    }

    /* --- a.c alive-title — Large title below number ---
       Ported from: iframe lines 1013-1023 */
    .project-column.active-collapsed .alive-title {
        position: absolute;
        top: calc(3px + var(--spacing-12, 12px) + 61px + var(--spacing-6, 6px));
        left: calc(3px + var(--spacing-12, 12px));
        font-size: var(--font-size-huge, 3rem);  /* 48px (8×6n) */
        font-weight: 800;
        color: var(--darkest);
        opacity: 1;
        margin: 0;
        padding: 0;
    }

    /* Partial divider — 72px accent line under title.
       Ported from: iframe lines 1029-1037 */
    .project-column.active-collapsed .alive-title::after {
        content: '';
        position: absolute;
        bottom: calc(-1 * var(--spacing-6, 6px));
        left: 0;
        width: var(--spacing-72, 72px);
        height: 3px;
        background-color: var(--current-accent);
    }

    /* --- a.c alive-preview (grid row 2) — hero asset area ---
       Ported from: iframe lines 1096-1110 */
    .project-column.active-collapsed .alive-preview {
        grid-column: 1;
        grid-row: 2;
        display: flex;
        align-items: center;
        justify-content: flex-end;
        flex: 1;
        min-height: 0;
        height: 100%;
        margin: 0;
        padding: 0;
        overflow: hidden;
        z-index: 1;
        opacity: 1;
    }

    /* --- a.c hero asset sizing + borders ---
       ALL a.c preview images/videos get top/bottom borders (iframe:733-738).
       Container border removed (iframe:728), content-hugging borders on img/video.
       To revert: height→auto, object-position→right center */
    .project-column.active-collapsed .alive-preview img,
    .project-column.active-collapsed .alive-preview video {
        width: auto;
        height: 100%;                           /* Fill preview height (iframe:1190) */
        max-height: 100%;
        max-width: 100%;
        object-fit: contain;
        object-position: right bottom;          /* Right-aligned, bottom-anchored (iframe:1194) */
        border-top: 3px solid var(--cool);      /* Content-hugging borders (iframe:735) */
        border-bottom: 3px solid var(--cool);   /* (iframe:736) */
        border-left: none;
        border-right: none;
    }

    /* P1 & P6 use --darkest borders (iframe:742-747) */
    .project-column[data-index="1"].active-collapsed .alive-preview img,
    .project-column[data-index="1"].active-collapsed .alive-preview video,
    .project-column[data-index="6"].active-collapsed .alive-preview img,
    .project-column[data-index="6"].active-collapsed .alive-preview video {
        border-color: var(--darkest);
    }
    /* END CLEAN-FIX-C8-P2B-F05-CASCADE-BORDERS — preview borders */

    /* START CLEAN-FIX-C8-P2B-F1-CAROUSEL — CSS transitions
       Ported from: iframe lines 1207-1270 (carousel wipe/push transition)
       To revert: Delete between START/END markers; carousel items won't animate. */

    .project-column.active-collapsed .alive-preview.carousel {
        position: relative;
        overflow: hidden;
        height: 100%;
        align-items: center;
    }

    .carousel-item {
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        width: 100%;
        transform: translateX(100%);
        opacity: 1;
        transition: none;
        pointer-events: none;
    }

    .carousel-item.active {
        transform: translateX(0);
        pointer-events: auto;
        position: absolute;
        z-index: 2;
        transition: transform 0.6s ease-in-out;
    }

    .carousel-item.exiting {
        transform: translateX(-100%);
        position: absolute;
        z-index: 1;
        transition: transform 0.6s ease-in-out;
    }

    .project-column.active-collapsed .carousel-item {
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: flex-end;
        border: none;
    }

    .project-column.active-collapsed .carousel-item img,
    .project-column.active-collapsed .carousel-item video {
        width: auto;
        height: auto;
        max-height: 100%;
        max-width: 100%;
        object-fit: contain;
        object-position: right center;
        border-top: 3px solid var(--cool);
        border-bottom: 3px solid var(--cool);
        border-left: none;
        border-right: none;
    }

    .project-column[data-index="1"].active-collapsed .carousel-item img,
    .project-column[data-index="1"].active-collapsed .carousel-item video,
    .project-column[data-index="6"].active-collapsed .carousel-item img,
    .project-column[data-index="6"].active-collapsed .carousel-item video {
        border-color: var(--darkest);
    }

    @media (prefers-reduced-motion: reduce) {
        .carousel-item { transition: none; }
    }
    /* END CLEAN-FIX-C8-P2B-F1-CAROUSEL */

} /* END @media (max-width: 819px) — Step 1c */

/* START CLEAN-FIX-C8-P2B-F05-CASCADE-BORDERS — Short-screen overrides (MOVED from line 80)
   CASCADE FIX: This block was originally at the top of the file (before Step 1c).
   On iPhone SE (375×667px), both max-height:720px AND max-width:991px match.
   Same-specificity rules resolve by SOURCE ORDER — later wins.
   By placing this AFTER Step 1c, the short-screen reductions (54px/30px/114px)
   correctly override the main block's values (72px/48px/200px).
   North star (iframe) has this block at line 1057 — AFTER main a.c CSS at line 921.
   To revert: Move this block back above B2 section (original position). */
@media (max-height: 720px) {
    .project-column.active-collapsed .alive-number {
        font-size: var(--font-size-r-number-short);  /* 54px/3.375rem — 9×6n (iframe:1059) */
    }

    .project-column.active-collapsed .alive-title {
        font-size: var(--font-size-r-title-short);   /* 30px/1.875rem — 5×6n (iframe:1066) */
        top: calc(3px + var(--spacing-12) + 46px + var(--spacing-6));  /* ~67px (iframe:1066) */
    }

    .project-column.active-collapsed .coords-system {
        min-height: 114px;                            /* 19×6n (iframe:1076) */
        margin-bottom: var(--spacing-6);              /* 1×6n — tighter gap (iframe:1076) */
    }

    .project-column.active-collapsed .alive-header {
        margin-bottom: 0;                             /* Remove gap (iframe:1081) */
    }

    .project-column.active-collapsed .alive-title::after {
        width: 54px;                                  /* 9×6n — proportional to 30px title (iframe:1086) */
    }
}
/* END CLEAN-FIX-C8-P2B-F05-CASCADE-BORDERS — Short-screen overrides */

/* START CLEAN-FIX-C8-P2B-F06-TRANSITIONS — d.c ↔ a.c state transition animations
   Ported from: iframe lines 1370-1401
   These animate coords-system, title, subtitle, and preview during state changes.
   Without them, d.c→a.c and a.c→d.c snap instantly.
   To revert: Delete between START/END markers. State changes revert to instant snap. */
.project-column .coords-system {
    transition: transform 0.35s var(--va-ease-out);
}

.project-column .alive-title {
    transition: transform 0.35s var(--va-ease-out),
                font-size 0.35s var(--va-ease-out),
                margin 0.35s var(--va-ease-out);
}

.project-column .alive-subtitle {
    transition: transform 0.35s var(--va-ease-out),
                margin 0.35s var(--va-ease-out);
}

.project-column .alive-preview {
    transition: transform 0.4s var(--va-ease-spring),
                opacity 0.3s ease;
}

@media (prefers-reduced-motion: reduce) {
    .project-column .coords-system,
    .project-column .alive-title,
    .project-column .alive-subtitle,
    .project-column .alive-preview {
        transition: none;
    }
}
/* END CLEAN-FIX-C8-P2B-F06-TRANSITIONS */

/* END CLEAN-FIX-C8-P1C-ALIVE-CONTENT */


/* ============================================
   STEP 1d: TOC BAR + INSTRUCTION BAR CSS
   START CLEAN-FIX-C8-P1D-TOC-INSTRUCTION
   Ported from: iframe-project-columns-v8-production.html lines 269-349, 1429-1761
   PORT ADAPTATION: All TOC selectors use #tocContainer (ID) to avoid collision
   with footer .toc-container in v3-footer-extensions-clean.css (line 142).
   Per-project accents mapped to production tokens (--cool, --blue, etc.)
   instead of iframe --v6-project-*-accent (not in production).
   P1 accent = --cool (per CLEAN-FIX-PROJECT1-ACCENT correction).
   To revert: Search CLEAN-FIX-C8-P1D-TOC-INSTRUCTION and delete between START/END markers
   ============================================ */

@media (max-width: 819px) {

    /* ============================================
       INSTRUCTION BAR
       Fixed bar below header: "DRAG: explore | LIFT: view"
       Visible only when body.has-active-collapsed is set by JS
       Ported from: iframe lines 274-349
       ============================================ */
    .instruction-bar {
        position: fixed;
        top: var(--reserved-header);
        left: 0;
        right: 0;
        height: var(--instruction-bar-height, 48px);
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 0 var(--spacing-18, 18px);
        background: var(--white);
        border-bottom: 1px solid var(--light);
        z-index: 99;
        transition: transform 0.25s ease, opacity 0.25s ease;
        /* Default: hidden until body.has-active-collapsed is set */
        transform: translateY(-100%);
        opacity: 0;
        pointer-events: none;
    }

    .instruction-bar.hidden {
        transform: translateY(-100%);
        opacity: 0;
    }

    body.has-active-collapsed .instruction-bar {
        transform: translateY(0);
        opacity: 1;
        pointer-events: auto;
    }

    .instruction-segment {
        display: flex;
        align-items: center;
        gap: var(--spacing-6, 6px);
    }

    .instruction-label {
        font-family: var(--font-primary);
        font-size: var(--font-size-specialized, 0.65rem);
        font-weight: 800;
        text-transform: uppercase;
        letter-spacing: 1px;
        color: var(--dark);
    }

    .instruction-action {
        font-family: var(--font-primary);
        font-size: var(--font-size-specialized, 0.65rem);
        font-weight: 500;
        text-transform: lowercase;
        letter-spacing: 1px;
        color: var(--warm);
    }

    /* ============================================
       TOC BAR — Mobile Project Navigation
       Fixed bottom bar with 6 project abbreviation indicators.
       All selectors use #tocContainer ID (avoids footer collision).
       Ported from: iframe lines 1429-1761 (final design only)
       ============================================ */

    #tocContainer {
        position: fixed;
        bottom: calc(var(--reserved-footer, 48px) + var(--spacing-12, 12px));
        left: 0;
        right: 0;
        height: var(--va-toc-height, 54px);
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 0 var(--spacing-12, 12px);
        width: 100%;
        gap: 0;
        background: var(--white);
        border-top: 1px solid var(--light);
        z-index: 99;
        transition: transform 0.3s ease, opacity 0.3s ease;
    }

    #tocContainer.hidden {
        transform: translateY(calc(100% + var(--spacing-24, 24px)));
        opacity: 0;
    }

    /* --- TOC Item: touch target per indicator ---
       CRITICAL OVERRIDE: footer extensions (v3-footer-extensions-clean.css:164) applies
       background: var(--darkest) + dark borders to ALL .toc-item elements globally.
       These resets prevent those footer styles from bleeding into the mobile TOC. */
    #tocContainer .toc-item {
        flex: 1;
        text-align: center;
        height: 48px;                           /* 8×6n — meets 44px touch target minimum */
        padding: 0;
        display: flex;
        flex-direction: row;                    /* Override footer's column direction */
        align-items: center;
        justify-content: center;
        cursor: pointer;
        position: relative;
        font-family: var(--font-primary);
        -webkit-tap-highlight-color: transparent;
        /* Reset footer extension .toc-item bleeding */
        background: transparent;
        border: none;
        width: auto;
    }

    /* --- TOC Indicator: text container (final design = no diamond clip) --- */
    #tocContainer .toc-indicator {
        display: block;
        position: relative;
        width: auto;
        height: auto;
        clip-path: none;
        border: none;
        background: transparent;
        transition: background 0.2s ease, border-color 0.2s ease;
    }

    /* --- TOC Inner: flat layout (no cube flip in final design) --- */
    #tocContainer .toc-item-inner {
        width: auto;
        height: auto;
        display: flex;
        align-items: center;
        justify-content: center;
        transform-style: flat;
        transform: none;
    }

    /* --- TOC Abbreviation (3-char): default state --- */
    #tocContainer .toc-abbrev-3 {
        display: inline-flex;
        position: relative;
        transform: none;
        font-family: var(--font-primary);
        font-size: var(--font-size-specialized, 0.65rem);
        font-weight: 700;
        color: var(--darkest);
        text-transform: uppercase;
        letter-spacing: 1px;
        width: 36px;                            /* 6×6n — fixed box */
        height: 36px;                           /* 6×6n — fixed box */
        align-items: center;
        justify-content: center;
        padding: 0;
        transition: all 0.2s ease;
        background: transparent;
    }

    /* Inactive items dimmed for visual hierarchy */
    #tocContainer .toc-item:not(.active) .toc-abbrev-3 {
        opacity: 0.6;
    }

    /* --- TOC ACTIVE STATE: dark box with accent border + angular clip --- */
    #tocContainer .toc-item.active .toc-abbrev-3 {
        background: var(--darkest);
        color: var(--lightest);
        clip-path: polygon(6px 0, 100% 0, 100% 100%, 0 100%, 0 6px);
        border: 1px solid var(--toc-accent, var(--warm));
        padding: 0;
    }

    /* Active underline — accent color bar under active item */
    #tocContainer .toc-item.active::after {
        content: '';
        position: absolute;
        bottom: 0;
        left: 50%;
        transform: translateX(-50%);
        width: 36px;
        height: 3px;
        background: var(--toc-accent, var(--warm));
        transition: all 0.2s ease;
    }

    /* Pressed visual feedback */
    #tocContainer .toc-item.pressed .toc-abbrev-3 {
        background: var(--darkest);
        color: var(--lightest);
        transform: scale(0.98);
    }

    /* --- TOC PULSE RING: diamond-shaped sequential pulse --- */
    #tocContainer .toc-item .pulse-ring {
        display: block;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 24px;
        height: 24px;
        border: 2px solid var(--toc-accent, var(--warm));
        border-radius: 0;
        clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
        opacity: 0;
        pointer-events: none;
        background: transparent;
        animation: none;
    }

    /* Active item: no pulse */
    #tocContainer .toc-item.active .pulse-ring {
        animation: none;
        opacity: 0;
    }

    /* Sequential pulse state (toggled by JS SequentialPulseController) */
    #tocContainer .toc-item.pulse-active .pulse-ring {
        opacity: 0.6;
        animation: toc-pulse-ring-expand 2s ease-out forwards;
    }

    /* --- Per-project accent colors (TOC uses data-project) --- */
    #tocContainer .toc-item[data-project="1"] { --toc-accent: var(--cool); }
    #tocContainer .toc-item[data-project="2"] { --toc-accent: var(--blue); }
    #tocContainer .toc-item[data-project="3"] { --toc-accent: var(--pink); }
    #tocContainer .toc-item[data-project="4"] { --toc-accent: var(--purple); }
    #tocContainer .toc-item[data-project="5"] { --toc-accent: var(--darkblue); }
    #tocContainer .toc-item[data-project="6"] { --toc-accent: var(--cyan); }

    /* --- Per-project accent colors for columns (uses data-index) --- */
    .project-column[data-index="1"] { --current-accent: var(--warm); }  /* Was --cool (#a9b0b2); north star uses --v6-project-1-accent: #797E80 = --warm */
    .project-column[data-index="2"] { --current-accent: var(--blue); }
    .project-column[data-index="3"] { --current-accent: var(--pink); }
    .project-column[data-index="4"] { --current-accent: var(--purple); }
    .project-column[data-index="5"] { --current-accent: var(--darkblue); }
    .project-column[data-index="6"] { --current-accent: var(--cyan); }

} /* END @media (max-width: 819px) — Step 1d */

/* Pulse keyframes (not breakpoint-scoped — animation runs if class applied) */
@keyframes toc-pulse-ring-expand {
    0% {
        transform: translate(-50%, -50%) scale(0.8);
        opacity: 0.8;
    }
    50% {
        transform: translate(-50%, -50%) scale(1.8);
        opacity: 0.4;
    }
    100% {
        transform: translate(-50%, -50%) scale(2.5);
        opacity: 0;
    }
}

/* END CLEAN-FIX-C8-P1D-TOC-INSTRUCTION */


/* ============================================
   STEP 2b: FULL EXPANDED (f.e) OVERLAY + TAB CSS
   START CLEAN-FIX-C8-P2B-FE-CSS
   Ported from: iframe-project-columns-v8-production.html
   Lines: 1804-2010 (overlay + f.prim), 2017-2146 (h.prim + h.sec),
          2489-2690 (f.sec), 2806-2876 (content body), 3113-3191 (overview)
   5-bar hierarchy: h.prim (48px) + h.sec (48px) + body (flex:1) + f.sec (42px) + f.prim (48px)
   To revert: Search CLEAN-FIX-C8-P2B-FE-CSS and delete between START/END markers
   ============================================ */

/* --- Desktop guard: hide f.e elements at ≥820px (shifted from 992px in P5-S3) --- */
@media (min-width: 820px) {
    .expanded-overlay,
    .uc-header-primary,
    .uc-header-secondary,
    .uc-footer-primary,
    .uc-footer-secondary,
    .footer-expand-hint,
    .mobile-mockups-header,
    .mobile-overview-header {
        display: none;
    }
}

/* START CLEAN-FIX-C8-P2-GRID-OVERLAY-HIDE
   Hide page-level .grid-overlay at responsive breakpoints.
   The DOM grid-overlay (project-column-styles.css:65, z-index:100) is a desktop
   decorative element. At ≤991px, project columns use their own scoped CSS grid
   via .alive-content::before (line 698). The DOM overlay bleeds over a.c and f.e
   bars because z:100 > z:95-97. North star has no .grid-overlay DOM element.
   To revert: Delete this media query block between START/END markers. */
@media (max-width: 819px) {
    .grid-overlay {
        display: none;
    }
}
/* END CLEAN-FIX-C8-P2-GRID-OVERLAY-HIDE */

@media (max-width: 819px) {

    /* ============================================
       EXPANDED OVERLAY CONTAINER
       Fixed positioning fills viewport minus header/footer
       ============================================ */
    .expanded-overlay {
        position: fixed;
        top: var(--reserved-header);
        left: 0;
        right: 0;
        bottom: var(--reserved-footer);
        background: var(--white);
        z-index: 95;
        opacity: 0;
        pointer-events: none;
        transition: opacity 240ms ease;
        display: flex;
        flex-direction: column;
    }

    .expanded-overlay.visible {
        opacity: 1;
        pointer-events: auto;
    }


/* ============================================
       H.PRIM — Header Primary (Project Identity Bar)
       Left: P# + title | Right: abbreviation in accent color
       ============================================ */
    .uc-header-primary {
        height: 48px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 0 var(--spacing-12, 12px);
        font-family: var(--font-primary);
        font-size: var(--font-size-small);
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 1px;
        color: var(--darkest);
        background: var(--white);
        border-left: 3px solid var(--active-accent, var(--current-accent));
        border-bottom: 1px solid var(--light);
    }

    .uc-hprim-left {
        display: flex;
        gap: var(--spacing-6, 6px);
        align-items: center;
        color: var(--darkest);
    }

    .uc-hprim-right {
        color: var(--active-accent, var(--current-accent));
        font-weight: 700;
    }

    /* ============================================
       H.SEC — Header Secondary (Tab-Specific Content Bar)
       Assets: mockupsTitle | Info: timeline | Overview: title + reading time
       ============================================ */
    .uc-header-secondary {
        height: 48px;
        font-size: var(--font-size-specialized, 0.65rem);
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 1px;
        color: var(--dark);
        background: var(--lightest);
        border-top: 1px solid var(--light);
        border-bottom: 1px solid var(--light);
        display: flex;
        align-items: center;
        padding: 0 var(--spacing-24, 24px);
        overflow: hidden;
    }

    .uc-header-secondary.uc-timeline-full {
        padding: 0;
        height: 48px;
        overflow: visible;
    }

    .uc-header-secondary.uc-hidden {
        display: none;
    }

    /* Darkest theme (Overview tab) */
    .uc-header-secondary.uc-darkest-theme {
        background: var(--darkest);
        border-top: none;
        border-bottom: 1px solid var(--dark);
        color: var(--lightest);
    }

    /* Overview h.sec flex layout — title left, reading time right */
    .hsec-overview-layout {
        display: flex;
        justify-content: space-between;
        align-items: center;
        width: 100%;
        gap: var(--spacing-24, 24px);
        transform: translateY(48px);
        transition: transform 288ms cubic-bezier(0.22, 0.80, 0.36, 1.0);
    }

    .hsec-overview-layout.hsec-title-revealed {
        transform: translateY(0);
    }

    .hsec-overview-layout.hsec-title-dismissing {
        transform: translateY(48px);
        transition: transform 288ms cubic-bezier(0.38, 0.0, 0.22, 1.0);
    }

    .hsec-overview-title {
        font-family: var(--font-primary);
        font-size: var(--font-size-specialized, 0.65rem);
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 1px;
        flex: 1;
    }

    .uc-header-secondary .hsec-overview-title { color: var(--dark); }
    .uc-header-secondary.uc-darkest-theme .hsec-overview-title { color: var(--white); }

    .hsec-overview-reading-time {
        font-family: var(--font-primary);
        font-size: var(--font-size-specialized, 0.65rem);
        font-weight: 400;
        color: var(--cool);
        white-space: nowrap;
        flex-shrink: 0;
    }

    .uc-header-secondary.uc-darkest-theme .hsec-overview-reading-time { color: var(--light); }

    /* h.sec category tags layout (P1/P6 — no timeline) */
    .hsec-category-layout {
        display: flex;
        align-items: center;
        gap: var(--spacing-6, 6px);
        height: 100%;
        padding: 0 var(--spacing-12, 12px);
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }

    .hsec-category-tag {
        font-family: var(--font-primary);
        font-size: var(--font-size-specialized, 0.65rem);
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.5px;
        color: var(--dark);
        white-space: nowrap;
        padding: var(--spacing-6, 6px) var(--spacing-12, 12px);
        border: 1px solid var(--light);
        border-left: 3px solid var(--active-accent, var(--current-accent));
    }

    /* START CLEAN-FIX-C8-P2B-VF-BATCH4-HSEC-MARQUEE — Fallback marquee CSS
       Ported from: north star lines 2404-2471 (hsec-fallback-marquee, skill-tag, title-item)
       To revert: Delete between START/END markers. P1/P6 h.sec reverts to empty/text. */

    /* Marquee container — fills h.sec height, clips track */
    .hsec-fallback-marquee {
        width: 100%;
        height: 42px;                               /* 7×6n — matches f.sec height */
        background: var(--lightest);
        display: flex;
        align-items: center;
        overflow: hidden;
        padding: 0 var(--spacing-24, 24px);         /* 4×6n — match h.sec padding */
    }

    /* Animated track — duplicated content scrolls left */
    .hsec-marquee-track {
        display: flex;
        align-items: center;
        animation: hsec-marquee-scroll 45s linear infinite;
        white-space: nowrap;
    }

    @keyframes hsec-marquee-scroll {
        0% { transform: translateX(0); }
        100% { transform: translateX(-50%); }
    }

    /* P1: Skill tags with octagonal clip-path (iframe:2427-2440) */
    .hsec-skill-tag {
        font-family: var(--font-secondary);
        font-size: var(--font-size-specialized, 0.65rem);
        font-weight: 700;
        letter-spacing: 1px;
        text-transform: uppercase;
        color: var(--dark);
        padding: var(--spacing-6, 6px) var(--spacing-12, 12px);
        border: 1px solid var(--light);
        background: transparent;
        margin-right: var(--spacing-12, 12px);
        clip-path: polygon(6px 0, calc(100% - 6px) 0, 100% 6px, 100% calc(100% - 6px), calc(100% - 6px) 100%, 6px 100%, 0 calc(100% - 6px), 0 6px);
        flex-shrink: 0;
    }

    /* Every 4th tag — subtle rhythm (iframe:2445, G3 accessibility fix) */
    .hsec-skill-tag:nth-child(4n+1) {
        border-color: var(--cool);
    }

    /* P6: Project title items (iframe:2451-2458) */
    .hsec-title-item {
        font-family: var(--font-secondary);
        font-size: var(--font-size-specialized, 0.65rem);
        font-weight: 700;
        letter-spacing: 1px;
        text-transform: uppercase;
        color: var(--dark);
        flex-shrink: 0;
    }

    /* Dot separator between titles (iframe:2461-2465) */
    .hsec-title-separator {
        color: var(--dark);
        margin: 0 var(--spacing-12, 12px);
        font-weight: 400;
        flex-shrink: 0;
    }

    /* Pause on hover (iframe:2468-2470) */
    .hsec-fallback-marquee:hover .hsec-marquee-track {
        animation-play-state: paused;
    }

    @media (prefers-reduced-motion: reduce) {
        .hsec-marquee-track {
            animation: none;
        }
        .hsec-fallback-marquee {
            overflow-x: auto;
        }
    }
    /* END CLEAN-FIX-C8-P2B-VF-BATCH4-HSEC-MARQUEE */

    /* ============================================
       EXPANDED CONTENT BODY — Tab Containers
       flex:1 fills space between headers and footers
       CSS containment for performance during content population
       ============================================ */
    .expanded-content {
        flex: 1;
        display: flex;
        flex-direction: column;
        overflow-y: auto;
        padding: var(--spacing-18, 18px);
        background-color: var(--white);
        contain: layout style paint;
        transition: opacity 180ms cubic-bezier(0.22, 0.80, 0.36, 1.0);
    }

    .tab-content {
        display: none;
    }

    .tab-content.active {
        display: block;
    }

    /* CLEAN-FIX-C8-VR-MARQUEE-RAF: Assets tab clips overflow — rAF handles visual scrolling via translate3d.
       Without this, masonry content overflows into the expanded-content scroll area.
       To revert: Remove this rule. */
    .tab-content[data-tab="assets"].active {
        overflow: hidden;
    }

    /* START CLEAN-FIX-C8-P2B-F5-OVERVIEW — Tab-specific active display
       Overview and info need flex layout for proper container sizing.
       Generic display:block above serves assets tab.
       To revert: Delete these two selectors. Tabs revert to display:block. */
    .tab-content[data-tab="overview"].active {
        display: flex;
        flex-direction: column;
        flex: 1;
        min-height: 0;                              /* Allow flex shrinking (iframe:4262) */
        min-width: 0;                               /* Prevent content inflation in flex column */
        background-color: var(--dark);
        padding: var(--spacing-18, 18px) 0;
        position: relative;
    }

    .tab-content[data-tab="info"].active {
        display: flex;
        flex-direction: column;
        flex: 1;
        overflow: hidden;
        min-height: 0;                              /* Allow flex shrinking (iframe:4262) */
    }

    /* START CLEAN-FIX-C8-P2B-VF-BATCH1-LAYOUT — Tab-specific expanded-content constraints
       Info + overview tabs need max-height to stop at f.sec top edge.
       294px = reserved-header(60) + h.prim(48) + h.sec(48) + f.sec(42) + f.prim(48) + gap(48) = 49×6n
       To revert: Delete between START/END markers. Tabs revert to unconstrained height. */

    /* Info tab — edge-to-edge stream, constrained height (iframe:5735-5739) */
    /* CLEAN-FIX-C8-VR-INFO-STREAM: Removed padding-top 18px — info-layout-content has its own padding.
       Extra 18px was wasting vertical space, reducing asset stream height.
       To revert: Restore padding: var(--spacing-18, 18px) 0 0 0 */
    .expanded-overlay .expanded-content:has(.tab-content[data-tab="info"].active),
    .expanded-overlay .expanded-content.expanded-content-info-active {
        overflow: hidden;
        padding: 0;                                  /* No extra padding — tile handles its own */
        max-height: calc(100vh - 294px);            /* Stop at f.sec top edge (iframe:5738) */
    }

    /* Overview tab — constrained height, sides-only padding (iframe:5751-5755) */
    .expanded-overlay .expanded-content:has(.tab-content[data-tab="overview"].active),
    .expanded-overlay .expanded-content.expanded-content-overview-active {
        overflow: hidden;
        max-height: calc(100vh - 294px);            /* Same constraint (iframe:5754) */
        padding: 0 var(--spacing-18, 18px);         /* Sides-only; tab-content handles top/bottom (iframe:5756) */
        background-color: var(--dark);              /* Explicit dark bg (north star line 5753) */
    }
    /* END CLEAN-FIX-C8-P2B-VF-BATCH1-LAYOUT */

    /* Scroll indicator */
    .responsive-overview-scroll-indicator {
        position: absolute;
        right: 0;
        top: 0;
        bottom: 0;
        width: var(--spacing-6, 6px);
        z-index: 10;
        pointer-events: none;
    }

    #overviewContent .responsive-overview-scroll-indicator {
        top: var(--spacing-24, 24px);
        bottom: var(--spacing-24, 24px);
    }

    .responsive-overview-scroll-track {
        position: absolute;
        right: 0;
        top: 0;
        bottom: 0;
        width: var(--spacing-6, 6px);
        background-color: var(--dark);
        opacity: 0.2;
    }

    .responsive-overview-scroll-thumb {
        position: absolute;
        width: var(--spacing-6, 6px);
        min-height: 24px;
        background-color: var(--white);
        border: 1px solid var(--black);
        transition: transform 0.3s linear;
        will-change: transform;
    }

    #overviewContent.no-scroll .responsive-overview-scroll-indicator {
        display: none;
    }
    /* END CLEAN-FIX-C8-P2B-F5-OVERVIEW */

    /* --- Directional tab slide animations ---
       3-phase: exit (48ms) → swap (72ms) → enter (132ms) = 252ms total */
    .tab-slide-exit-left {
        transform: translateX(-24px);
        opacity: 0;
        transition: transform 48ms ease, opacity 48ms ease;
    }

    .tab-slide-exit-right {
        transform: translateX(24px);
        opacity: 0;
        transition: transform 48ms ease, opacity 48ms ease;
    }

    .tab-slide-enter-left  { transform: translateX(-24px); opacity: 0; }
    .tab-slide-enter-right { transform: translateX(24px); opacity: 0; }

    .tab-slide-enter-active {
        transform: translateX(0);
        opacity: 1;
        transition: transform 132ms cubic-bezier(0.22, 0.80, 0.36, 1.0),
                    opacity 132ms ease;
    }

    /* ============================================
       F.SEC — Footer Secondary (Tab-Specific Controls)
       Hidden by default, shown via .visible class
       ============================================ */
    .uc-footer-secondary {
        position: fixed;
        bottom: calc(var(--reserved-footer) + 48px);
        left: 0;
        right: 0;
        z-index: 97;
        height: 42px;
        font-size: var(--font-size-specialized, 0.65rem);
        color: var(--dark);
        background: var(--lightest);
        border-top: 1px solid var(--light);
        display: none;
        align-items: center;
        padding: 0 var(--spacing-24, 24px);
        overflow: hidden;
    }

    .uc-footer-secondary.visible {
        display: flex;
    }

    .uc-footer-secondary.uc-darkest-theme {
        background: var(--darkest);
        border-top: 1px solid var(--dark);
    }

    /* f.sec 2-column layout */
    .uc-footer-secondary-2col {
        display: flex;
        align-items: center;
        justify-content: space-between;
        width: 100%;
    }

    .uc-fsec-col-left, .uc-fsec-col-right {
        display: flex;
        align-items: center;
        gap: 0;
    }

    /* Production buttons (shared across f.sec tabs) */
    .uc-footer-secondary .uc-production-btn {
        width: 30px;
        height: 30px;
        background-color: var(--lightest);
        border: 1px solid rgba(48, 51, 51, 0.22);
        border-left: 2px solid var(--dark);
        font-family: var(--font-primary);
        font-size: var(--font-size-small);
        color: var(--dark);
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        transition: all 0.15s ease;
    }

    .uc-footer-secondary .uc-production-btn:hover {
        background-color: var(--light);
        color: var(--black);
    }

    .uc-footer-secondary .uc-production-btn.active,
    .uc-footer-secondary .uc-production-btn.speed-active {
        background-color: var(--dark);
        color: var(--white);
    }

    .uc-footer-secondary .uc-production-btn.speed-btn {
        font-size: var(--font-size-large, 1.1rem);
        min-width: 42px;                            /* 7×6n (was 40px — 6n compliance) */
        padding: 0 var(--spacing-12, 12px);
    }

    /* Module indicator (Info tab f.sec) */
    .uc-fsec-module-indicator {
        display: flex;
        align-items: center;
        gap: var(--spacing-6, 6px);
        font-size: var(--font-size-specialized, 0.65rem);
        font-weight: 500;
        color: var(--dark);
        text-transform: uppercase;
        letter-spacing: 1px;
    }

    .uc-fsec-module-node {
        width: 6px;
        height: 6px;
        border-radius: 50%;
        background: var(--active-accent, var(--current-accent));
        animation: fsec-module-pulse 2s ease-in-out infinite;
    }

    .uc-footer-secondary.uc-darkest-theme .uc-production-btn {
        background: var(--darkest);
        color: var(--lightest);
        border: 1px solid rgba(121, 126, 128, 0.24);
        border-left: 2px solid var(--light);
    }

    /* START CLEAN-FIX-C8-P2B-VF-BATCH2-DARKEST-FSEC — f.sec button refinements
       Ported from: north star lines 2554-2665 (first-child, darkest speed-btn, hover, active)
       To revert: Delete between START/END markers. Buttons revert to base styling. */

    /* First button — no heavy inset at left edge (iframe:2554) */
    .uc-footer-secondary .uc-production-btn:first-child {
        border-left: 1px solid rgba(48, 51, 51, 0.22);
    }

    /* Darkest theme first button (iframe:2634) */
    .uc-footer-secondary.uc-darkest-theme .uc-production-btn:first-child {
        border-left: 1px solid rgba(121, 126, 128, 0.24);
    }

    /* Darkest theme speed buttons — lowercase text, wider (iframe:2656-2665) */
    .uc-footer-secondary.uc-darkest-theme .uc-production-btn.speed-btn {
        font-size: var(--font-size-specialized, 0.65rem);   /* One step down from default */
        min-width: 48px;                                    /* 8×6n */
        text-transform: lowercase;
        letter-spacing: 0.5px;
    }

    /* Darkest theme hover — strengthened borders (iframe:2639-2647) */
    .uc-footer-secondary.uc-darkest-theme .uc-production-btn:hover {
        background: var(--dark);
        color: var(--white);
        border-top-color: rgba(121, 126, 128, 0.48);
        border-right-color: rgba(121, 126, 128, 0.48);
        border-bottom-color: rgba(121, 126, 128, 0.48);
    }

    /* Darkest theme active/speed-active (iframe:2649-2653) */
    .uc-footer-secondary.uc-darkest-theme .uc-production-btn.active,
    .uc-footer-secondary.uc-darkest-theme .uc-production-btn.speed-active {
        background: var(--dark);
        color: var(--white);
    }
    /* END CLEAN-FIX-C8-P2B-VF-BATCH2-DARKEST-FSEC */

    /* START CLEAN-FIX-C8-P4B-TYPE-TOGGLE-CSS
       Aa type size toggle button — border separator + type scale overrides.
       Snap change (no transition) — Brutalist decisive state change.
       Ported from: iframe lines 3459-3481 (CLEAN-FIX-PHASE8A-GATE-TYPE-TOGGLE)
       To revert: Delete everything between START/END markers. */
    .uc-footer-secondary .uc-type-toggle {
        border-left: 2px solid var(--light);
        margin-left: var(--spacing-6);
    }
    .uc-footer-secondary.uc-darkest-theme .uc-type-toggle {
        border-left: 2px solid rgba(121, 126, 128, 0.48);
    }
    .responsive-overview-container.uc-type-large h3,
    .responsive-overview-container.uc-type-large p {
        font-size: var(--font-size-standard);
    }
    .responsive-overview-container.uc-type-large li {
        font-size: var(--font-size-standard);
    }
    /* END CLEAN-FIX-C8-P4B-TYPE-TOGGLE-CSS */

    /* START CLEAN-FIX-C8-P4C-GUIDE-MARQUEE-CSS
       P6 overview f.sec guide-string marquee (CSS animation).
       Reuses @keyframes hsec-marquee-scroll (line 1513).
       Ported from: iframe lines 2667-2708
       To revert: Delete everything between START/END markers. */
    .fsec-guide-marquee {
        width: 100%;
        height: 42px;
        display: flex;
        align-items: center;
        overflow: hidden;
        /* Marquee scrolls behind absolutely-positioned Aa toggle — toggle has its own bg mask */
    }
    .fsec-guide-track {
        display: flex;
        align-items: center;
        animation: hsec-marquee-scroll 45s linear infinite;
        white-space: nowrap;
    }
    .fsec-guide-item {
        font-family: var(--font-secondary);
        font-size: var(--font-size-specialized);
        font-weight: 500;
        color: var(--lightest);
        text-transform: uppercase;
        letter-spacing: 1px;
        flex-shrink: 0;
    }
    .fsec-guide-separator {
        color: var(--dark);
        margin: 0 12px;
        font-weight: 400;
        flex-shrink: 0;
    }
    .fsec-guide-marquee:hover .fsec-guide-track {
        animation-play-state: paused;
    }
    /* END CLEAN-FIX-C8-P4C-GUIDE-MARQUEE-CSS */

    /* START CLEAN-FIX-C8-P4D-P6-BOUNCE-CSS
       P6 overview bounce — CSS-only translateY animation on panel content.
       Mirrors about.html staticContentBounce pattern (v3-about-page.css:1664).
       Uses percentage-based translateY so it adapts to any content height.
       Applied via .p6-bounce-active class toggled by JS type toggle.
       To revert: Delete everything between START/END markers. */
    /* Bounce animation keyframes + child selector live here; override in v3-overview-overlay.css
       handles justify-content specificity (B9 centering rule loads after this file) */
    .responsive-overview-container.p6-bounce-active {
        overflow: hidden;
    }
    .responsive-overview-container.p6-bounce-active > * {
        animation: p6OverviewCrawl 14s ease-in-out infinite;
    }
    @keyframes p6OverviewCrawl {
        0%, 12% {
            transform: translateY(0);
        }
        44%, 56% {
            transform: translateY(-78px); /* 13×6n — clears ~67px overflow + 11px buffer */
        }
        88%, 100% {
            transform: translateY(0);
        }
    }
    /* END CLEAN-FIX-C8-P4D-P6-BOUNCE-CSS */

    /* ============================================
       F.PRIM — Footer Primary (Tab Bar + Close Button)
       Fixed bottom bar, hidden by default
       ============================================ */
    .uc-footer-primary {
        position: fixed;
        bottom: var(--reserved-footer);
        left: 0;
        right: 0;
        height: 48px;
        display: none;
        align-items: center;
        background: var(--white);
        border-top: 1px solid var(--light);
        z-index: 96;
        padding-right: 0;
    }

    .uc-footer-primary.visible {
        display: flex;
    }

    .tile-tabs {
        display: flex;
        flex: 1;
        overflow: visible;
    }

    .tile-tab-btn {
        flex: 1;
        background: transparent;
        border: none;
        color: var(--cool);
        font-family: var(--font-primary);
        font-size: var(--font-size-specialized, 0.65rem);
        font-weight: 500;
        text-transform: uppercase;
        letter-spacing: 1px;
        padding: var(--spacing-12, 12px);
        height: 48px;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        position: relative;
        overflow: visible;
        transition: color 0.15s ease;
    }

    .tile-tab-btn.active {
        color: var(--darkest);
        font-weight: 700;
        background: var(--lightest);
    }

    .tile-tab-btn.active::after {
        content: '';
        position: absolute;
        bottom: 0;
        left: 0;
        right: 0;
        height: 2px;
        background: var(--active-accent, var(--current-accent));
    }

    .tile-tab-btn:hover:not(.active) {
        color: var(--warm);
    }

    /* Close cell — 48px rightmost area */
    .tile-close-cell {
        width: 48px;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
        border-left: 1px solid var(--light);
    }

    /* Octagon close icon */
    .tile-x-icon-wrapper {
        position: relative;
        width: 48px;
        height: 48px;
        display: flex;
        align-items: center;
        justify-content: center;
        overflow: visible;
        cursor: pointer;
    }

    .tile-x-icon {
        width: 48px;
        height: 48px;
        background: rgba(var(--lightest-rgb, 235, 235, 235), var(--opacity-strong, 0.5));
        border: 2px solid transparent;
        border-radius: 0;
        clip-path: polygon(29.3% 0%, 70.7% 0%, 100% 29.3%, 100% 70.7%, 70.7% 100%, 29.3% 100%, 0% 70.7%, 0% 29.3%);
        color: var(--dark);
        font-size: var(--font-size-standard, 0.9rem);
        display: flex;
        align-items: center;
        justify-content: center;
        transition: all 0.15s ease;
        position: relative;
        z-index: 1;
    }

    .tile-x-node {
        position: absolute;
        width: 3px;
        height: 3px;
        border-radius: 50%;
        background: var(--light);
        border: 1px solid var(--dark);
        transition: all 0.15s ease;
        z-index: 2;
        transform: translate(-50%, -50%);
    }

    .tile-x-node.node-top    { top: 0%;   left: 50%;  }
    .tile-x-node.node-right  { top: 50%;  left: 100%; }
    .tile-x-node.node-bottom { top: 100%; left: 50%;  }
    .tile-x-node.node-left   { top: 50%;  left: 0%;   }

    .tile-x-icon-wrapper:hover .tile-x-icon {
        background: var(--lightest);
        border-color: var(--warm);
        color: var(--darkest);
        font-weight: 700;
    }

    .tile-x-icon-wrapper:hover .tile-x-node {
        width: 6px;
        height: 6px;
        background: var(--active-accent, var(--current-accent));
        border-color: var(--active-accent, var(--current-accent));
    }

    /* ============================================
       OVERVIEW CONTAINER — Dark bg + Clip-path
       ============================================ */
    /* Override desktop .overview-content rules from project-column-styles.css line 2324
       (display:flex, width:max-content) that collide with .overview-content class on #overviewPanel.
       This is the ROOT CAUSE of the 3-column/horizontal text layout bug. */
    .responsive-overview-container {
        display: block;                             /* Override desktop display:flex (project-column-styles:2325) */
        width: auto;                                /* Override desktop width:max-content (project-column-styles:2327) */
        flex: 1;
        min-height: 0;
        min-width: 0;                               /* Allow flex shrink below content min-width */
        max-width: 100%;                            /* Prevent content from inflating beyond parent */
        align-self: stretch;                        /* Explicit stretch to fill parent width */
        background-color: var(--darkest);
        clip-path: polygon(2% 0%, 100% 0%, 100% 100%, 0% 100%, 0% 84%);
        -webkit-clip-path: polygon(2% 0%, 100% 0%, 100% 100%, 0% 100%, 0% 84%);
        padding: 0 var(--spacing-24, 24px);
        border-top: var(--spacing-24, 24px) solid var(--darkest);
        border-bottom: var(--spacing-24, 24px) solid var(--darkest);
        color: var(--white);
        overflow-y: auto;
        overflow-x: hidden;
        overflow-wrap: break-word;                  /* Prevent long words from overflowing */
        word-break: break-word;                     /* Safari fallback */
        scrollbar-width: none;
    }

    .responsive-overview-container::-webkit-scrollbar {
        display: none;
    }

    .responsive-overview-container,
    .responsive-overview-container * {
        color: var(--white);
    }

    /* START CLEAN-FIX-C8-P2B-VF-OVERVIEW-ENHANCED-TYPO
       Enhanced typography for overview content on darkest background.
       Ported from: north star lines 5033-5208, 3308-3367, 2578-2582
       Requires: .enhanced + .typo-v2 classes on .overview-content element (set via JS)
       To revert: Delete between START/END markers. Overview text reverts to base white. */

    /* === A. ENHANCED BASE TYPOGRAPHY === */

    .overview-content.enhanced h3 {
        font-family: var(--font-primary);
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 2px;
        text-decoration: underline;
        text-decoration-thickness: 2px;
        text-underline-offset: 4px;
        text-decoration-color: var(--current-accent);
        padding-left: var(--spacing-24);
        position: relative;
        margin: var(--spacing-24) 0 var(--spacing-12);
    }

    .overview-content.enhanced h3::before {
        content: '';
        width: 8px;
        height: 8px;
        background: var(--current-accent);
        border: 2px solid var(--dark);
        transform: rotate(45deg);
        position: absolute;
        left: 0;
        top: 50%;
        margin-top: -4px;
    }

    .overview-content.enhanced p {
        font-family: var(--font-secondary);
        line-height: 1.6;
        color: var(--light);                        /* 8.2:1 contrast on --darkest */
        margin-bottom: var(--spacing-18);
    }

    .overview-content.enhanced strong {
        color: var(--lightest);
        font-weight: 700;
        background-color: rgba(255, 255, 255, 0.1);
        padding: 2px 6px;
        display: inline;
    }

    .overview-content.enhanced h4 {
        font-family: var(--font-primary);
        font-size: var(--font-size-standard);
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 1.5px;
        color: var(--lightest);
        padding-left: var(--spacing-24);
        position: relative;
        margin: var(--spacing-24) 0 var(--spacing-6);
    }

    .overview-content.enhanced h4::before {
        content: '';
        width: 6px;
        height: 6px;
        background: var(--current-accent);
        transform: rotate(45deg);
        position: absolute;
        left: 4px;
        top: 50%;
        margin-top: -3px;
    }

    .overview-content.enhanced h5 {
        font-family: var(--font-primary);
        font-size: var(--font-size-small);
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 1px;
        color: var(--cool);
        margin: var(--spacing-12) 0 var(--spacing-6);
    }

    .overview-content.enhanced .process-questions em { color: var(--warm); font-style: italic; }
    .overview-content.enhanced .process-methods { color: var(--cool); font-size: var(--font-size-specialized); font-style: italic; }
    .overview-content.enhanced .gateway-marker { color: var(--current-accent); }
    .overview-content.enhanced mark { background: rgba(255, 255, 255, 0.08); color: var(--warm); padding: 2px 4px; }
    .overview-content.enhanced hr { border: none; border-top: 1px solid var(--dark); margin: var(--spacing-24) 0; }

    /* === B. TYPO-V2 WINNER — Left accent bar headings === */

    .overview-content.enhanced.typo-v2 h3 {
        text-decoration: none;
        border-left: 3px solid var(--current-accent);
        padding-left: var(--spacing-12);
        position: static;
        color: var(--white);
    }

    /* Title h3 — bottom underline, no left bar */
    .overview-content.enhanced.typo-v2 h3:first-child {
        border-left: none;
        border-bottom: 2px solid var(--current-accent);
        padding-left: 0;
        padding-bottom: var(--spacing-24);
        margin-top: 0;
        margin-bottom: var(--spacing-24);
    }

    .overview-content.enhanced.typo-v2 h3::before {
        display: none;
    }

    /* Section headings — lighter weight, secondary font */
    .overview-content.enhanced.typo-v2 h3 ~ h3 {
        padding-top: 0;
        margin-top: 0;
        font-family: var(--font-secondary);
        font-weight: var(--font-weight-medium);
        color: var(--light);
    }

    .overview-content.enhanced.typo-v2 hr.section-divider {
        border: none;
        width: 60%;
        height: 1px;
        background-color: var(--dark);
        margin: var(--spacing-24) auto var(--spacing-36) auto;
    }

    .overview-content.enhanced.typo-v2 strong {
        font-weight: 700;
        background-color: color-mix(in srgb, var(--current-accent) 12%, transparent);
    }

    .overview-content.enhanced.typo-v2 p {
        color: var(--light);
    }

    /* === C. SCROLL-V5 BRACKET CAPS === */

    #overviewContent.scroll-v5 .responsive-overview-scroll-indicator {
        border-top: none;
        border-bottom: none;
    }

    #overviewContent.scroll-v5 .responsive-overview-scroll-track {
        width: 4px;
        background-color: color-mix(in srgb, var(--dark) 20%, transparent);
        opacity: 1;
        position: absolute;
        right: 0; top: 0; bottom: 0;
    }

    /* Top bracket ⊓ */
    #overviewContent.scroll-v5 .responsive-overview-scroll-track::before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        height: 4px;
        border-top: 1px solid var(--warm);
        border-left: 1px solid var(--warm);
        border-right: 1px solid var(--warm);
    }

    /* Bottom bracket ⊔ */
    #overviewContent.scroll-v5 .responsive-overview-scroll-track::after {
        content: '';
        position: absolute;
        bottom: 0;
        left: 0;
        right: 0;
        height: 4px;
        border-bottom: 1px solid var(--warm);
        border-left: 1px solid var(--warm);
        border-right: 1px solid var(--warm);
    }

    #overviewContent.scroll-v5 .responsive-overview-scroll-thumb {
        width: 4px;
        background-color: var(--lightest);
        border-left: none;
        border-right: none;
        border-top: 2px solid var(--current-accent);
        border-bottom: 2px solid var(--current-accent);
    }

    #overviewContent.scroll-v5 .responsive-overview-scroll-thumb::before {
        display: none;
    }

    /* === D. PRODUCTION GROUP WRAPPER === */

    .uc-fsec-production-group {
        display: flex;
        height: 30px;                               /* 5×6n */
        align-items: center;
    }

    /* END CLEAN-FIX-C8-P2B-VF-OVERVIEW-ENHANCED-TYPO */

    /* ============================================
       FOOTER EXPAND HINT
       ============================================ */
    .footer-expand-hint {
        position: fixed;
        bottom: calc(var(--reserved-footer) + 48px + 42px);
        left: 50%;
        transform: translateX(-50%);
        font-family: var(--font-primary);
        font-size: var(--font-size-specialized, 0.65rem);
        color: var(--cool);
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.3s ease;
        z-index: 98;
    }

    /* ============================================
       MOBILE HEADERS — Show/hide per tab
       ============================================ */
    .mobile-mockups-header,
    .mobile-overview-header {
        position: fixed;
        top: calc(var(--reserved-header) + 48px);
        left: 0;
        right: 0;
        height: 48px;
        display: none;
        align-items: center;
        justify-content: space-between;
        padding: 0 var(--spacing-12, 12px);
        background: var(--white);
        border-bottom: 1px solid var(--light);
        z-index: 96;
        font-family: var(--font-primary);
        font-size: var(--font-size-specialized, 0.65rem);
    }

    .mobile-mockups-header.visible,
    .mobile-overview-header.visible {
        display: flex;
    }

    .mockups-title,
    .overview-expanded-title {
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 1px;
        color: var(--dark);
    }

    .mockups-controls,
    .overview-controls {
        display: flex;
        align-items: center;
        gap: var(--spacing-6, 6px);
    }

    .speed-selection {
        display: flex;
        gap: 0;
    }

    .mobile-mockups-header .speed-btn,
    .mobile-mockups-header .pause-btn,
    .mobile-mockups-header .restart-btn,
    .mobile-overview-header .speed-btn,
    .mobile-overview-header .pause-btn {
        width: 30px;
        height: 30px;
        background: transparent;
        border: 1px solid var(--light);
        font-family: var(--font-primary);
        font-size: var(--font-size-small);
        color: var(--dark);
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .mobile-mockups-header .speed-btn.active,
    .mobile-overview-header .speed-btn.active {
        background: var(--dark);
        color: var(--white);
    }

} /* END @media (max-width: 819px) — Step 2b */

/* START CLEAN-FIX-P5-S7C2B-M2-SET6-PULSE
   Set 6 tier selection (2026-04-16): Medium M-1 Gentle Swell.

   Element: .uc-fsec-module-node (6×6 dot inside .uc-fsec-module-indicator
   flex container at line ~1809). Role: Info tab f.sec status heartbeat.
   Scope: Mobile active state only (Info tab is mobile-only per project scope).
   Variation source: test-pulse-variations.html line 174-178 (medium-gentle-swell).
   Tier rationale: Matches Set 3's M-1 vocabulary — both use scale 1↔1.15 +
   opacity 0.6↔0.85 ease-in-out. Creates vocabulary consistency for scale-
   based Medium pulses across the mobile experience.

   Change: Keyframe BODY swap only. Keyframe NAME `fsec-module-pulse`
   preserved — the selector at `.uc-fsec-module-node` (L~1814) continues
   to reference it unchanged. No selector edit required. This preserves
   selector-level revert safety and minimizes diff scope.

   Body: scale 0.8↔1.2 + opacity 0.4↔1 (legacy, wider-range pulse)
     → scale 1↔1.15 + opacity 0.6↔0.85 (M-1, restrained gentle swell).

   Timing note: Selector animation-duration stays `2s` (legacy) rather
   than M-1's spec 2400ms. 400ms delta is imperceptible and keeping the
   selector untouched makes this commit atomic at a single file location.
   Can be tuned later if needed.

   Dependencies: None. Reads --active-accent / --current-accent token chain.

   Reversibility: Search CLEAN-FIX-P5-S7C2B-M2-SET6-PULSE, delete between
   START/END markers — keyframe body reverts to legacy scale 0.8↔1.2 +
   opacity 0.4↔1. Selector + keyframe name unchanged either way.

   Verify:
   - Mobile active state, open Info tab → .uc-fsec-module-node dot gently
     swells scale 1↔1.15 with opacity 0.6↔0.85 over 2s ease-in-out.
   - Sibling label text stays perfectly still (jitter verified absent on
     2026-04-16; span IS already the animated target per V3EC.js:1838).
   - prefers-reduced-motion: reduce → suppressed (pending C2-6 gate ext).
*/
@keyframes fsec-module-pulse {
    0%, 100% { transform: scale(1);    opacity: 0.6;  }
    50%      { transform: scale(1.15); opacity: 0.85; }
}
/* END CLEAN-FIX-P5-S7C2B-M2-SET6-PULSE */

/* Tab slide: respect prefers-reduced-motion */
@media (prefers-reduced-motion: reduce) {
    .tab-slide-exit-left,
    .tab-slide-exit-right,
    .tab-slide-enter-left,
    .tab-slide-enter-right,
    .tab-slide-enter-active {
        transform: none;
        transition: none;
    }
}

/* END CLEAN-FIX-C8-P2B-FE-CSS */


/* ============================================
   STEP 2d: F.E CONTENT STYLING
   START CLEAN-FIX-C8-P2D-FE-CONTENT
   Styles for dynamically populated f.e tab content:
   assets grid, info panel (subtitle, impact, categories, timeline), overview sections.
   To revert: Search CLEAN-FIX-C8-P2D-FE-CONTENT and delete between START/END markers
   ============================================ */

@media (max-width: 819px) {

    /* START CLEAN-FIX-C8-P2B-F4-MASONRY-MARQUEE — Assets masonry + marquee CSS
       Ported from: iframe lines 2906-3099 (masonry, marquee, captions, P4 single-column)
       To revert: Delete between START/END markers, restore flat grid layout */

    /* --- Assets Grid base (fallback for non-masonry) --- */
    .assets-grid {
        display: grid;
        grid-template-columns: 1fr;
        gap: var(--spacing-12, 12px);
    }

    /* --- Masonry layout override (2-column zigzag) --- */
    /* CLEAN-FIX-C8-VR-MARQUEE-RAF: Changed overflow from hidden → visible
       Root cause: overflow:hidden made scrollHeight === clientHeight, so rAF loop
       calculated wrapPoint=0 ("content fits") and skipped all scrolling.
       overflow:visible lets grid report true content height for rAF wrap calculation.
       To revert: Restore overflow: hidden. */
    .assets-grid.masonry-layout {
        display: flex;                                   /* Override grid (iframe:2954) */
        gap: var(--spacing-24, 24px);                    /* 4×6n (iframe:2955) */
        padding: 0 var(--spacing-18, 18px);              /* 3×6n side padding (iframe:2956) */
        height: 100%;
        overflow: visible;
    }

    .responsive-masonry-column {
        width: calc(50% - var(--spacing-12, 12px));      /* Half minus half-gap (iframe:2963) */
        display: flex;
        flex-direction: column;
        gap: var(--spacing-192, 192px);                  /* 32×6n masonry gap (iframe:2966) */
    }

    /* Zigzag offset for second column */
    .responsive-masonry-column:nth-child(2) {
        margin-top: var(--masonry-offset, 96px);         /* Dynamic JS override (iframe:2971) */
    }

    /* START CLEAN-FIX-C8-VR-MASONRY-MOBILE — Neutralize double spacing
       Root cause: v3-mockups-marquee.css:44 sets margin-bottom: var(--masonry-gap, 192px) on .asset-container.
       Combined with gap: 192px on .responsive-masonry-column = 384px total vertical space.
       Fix: Zero out margin-bottom since flex gap already provides 192px spacing.
       To revert: Remove margin-bottom: 0 line below. */
    .responsive-masonry-column .asset-container {
        position: relative;
        width: 100%;
        margin-bottom: 0;                              /* CLEAN-FIX-C8-VR-MASONRY-MOBILE: neutralize base 192px margin */
    }
    /* END CLEAN-FIX-C8-VR-MASONRY-MOBILE */

    .responsive-masonry-column .asset-item {
        width: 100%;
        background: var(--lightest);
        border: 1px solid var(--light);
        overflow: hidden;
    }

    .responsive-masonry-column .asset-item video,
    .responsive-masonry-column .asset-item img {
        width: 100%;
        height: auto;
        display: block;
        object-fit: contain;
    }

    /* Per-project static offset fallbacks (JS dynamic calc overrides) */
    .project-1 .responsive-masonry-column:nth-child(2) { --masonry-offset: 108px; }
    .project-2 .responsive-masonry-column:nth-child(2) { --masonry-offset: 174px; }
    .project-3 .responsive-masonry-column:nth-child(2) { --masonry-offset: 148px; }
    .project-4 .responsive-masonry-column:nth-child(2) { --masonry-offset: 0px; }
    .project-5 .responsive-masonry-column:nth-child(2) { --masonry-offset: 105px; }
    .project-6 .responsive-masonry-column:nth-child(2) { --masonry-offset: 120px; }

    /* P4: Single centered column (iframe:3094-3098) */
    .assets-grid.masonry-layout.single-column { justify-content: center; }
    .assets-grid.masonry-layout.single-column .responsive-masonry-column {
        width: calc(65% - var(--spacing-12, 12px));
        margin-top: 0;
    }

    /* --- Captions (placed outside .asset-item, inside .asset-container) --- */
    .responsive-asset-caption {
        margin-top: var(--spacing-18, 18px);
        padding: var(--spacing-12, 12px);
        width: calc(100% - 6px);
        border: 3px solid var(--light);
        background-color: var(--white);
        box-sizing: border-box;
        font-family: var(--font-secondary);
        font-size: var(--font-size-specialized);
        line-height: 1.4;
    }

    .responsive-asset-caption .caption-title {
        font-weight: 500;
        margin-bottom: var(--spacing-6, 6px);
        letter-spacing: 0.2px;
        color: var(--darkest);
    }

    .responsive-asset-caption .caption-desc {
        font-weight: 400;
        color: var(--warm);
        margin: 0;
    }

    .responsive-asset-caption em { font-style: italic; font-weight: 500; }

    /* Per-project caption shadows + P1 hidden */
    .project-1 .responsive-asset-caption { display: none; }
    .project-2 .responsive-asset-caption { box-shadow: 3px 3px 0 rgba(0, 0, 255, 0.2); }
    .project-3 .responsive-asset-caption { box-shadow: 3px 3px 0 rgba(255, 0, 68, 0.2); }
    .project-4 .responsive-asset-caption { box-shadow: 3px 3px 0 rgba(170, 0, 255, 0.2); }
    .project-5 .responsive-asset-caption { box-shadow: 3px 3px 0 rgba(7, 7, 51, 0.2); }
    .project-6 .responsive-asset-caption { box-shadow: 3px 3px 0 rgba(0, 247, 255, 0.2); }

    /* START CLEAN-FIX-C8-VR-MARQUEE-RAF — CSS animation replaced by JS rAF loop
       The CSS @keyframes approach caused position jumps on speed changes because
       browsers recalculate animation position when duration changes.
       JS rAF with explicit position state eliminates all jumps.
       To revert: Restore @keyframes assets-grid-scroll + .scrolling animation rules. */

    /* Keep will-change for GPU compositing (JS applies translate3d) */
    .assets-grid.scrolling {
        will-change: transform;
    }

    /* START CLEAN-FIX-P5-S7A-M5-BREATHE-GRID
       Breathe animation on rAF-managed .assets-grid when paused.
       Companion to .marquee-content.paused in v3-mockups-marquee.css (desktop path).
       Uses standalone scale property to compose with rAF's transform: translate3d().
       To revert: Delete this rule between START/END markers. */
    .assets-grid.paused {
        animation: breathe 2.4s ease-in-out infinite;
    }
    /* END CLEAN-FIX-P5-S7A-M5-BREATHE-GRID */

    /* Fallback for prefers-reduced-motion: no scrolling, manual overflow */
    @media (prefers-reduced-motion: reduce) {
        .assets-grid { overflow-y: auto; }
    }
    /* END CLEAN-FIX-C8-VR-MARQUEE-RAF CSS */

    /* Speed classes — retained for button active-state styling only (rAF uses JS speed map) */
    .assets-grid.speed-slow { --assets-marquee-duration: 180s; }
    .assets-grid.speed-default { --assets-marquee-duration: 60s; }
    .assets-grid.speed-fast { --assets-marquee-duration: 20s; }
    /* END CLEAN-FIX-C8-P2B-F4-MASONRY-MARQUEE */

    /* START CLEAN-FIX-C8-P2B-F3-INFO-R3 — Base R3 layout-tile CSS
       Ported from: iframe lines 4048-4230 (CLEAN-FIX-V8-G7-INFO-CONTENT-BASE-R3)
       These BASE rules are required for the height-tier overrides (B5/B6/B7, lines 280-387) to function.
       To revert: Delete between START/END markers. Info tab reverts to flat layout. */

    /* START CLEAN-FIX-C8-VR-INFO-STREAM — R3 panel: north star height model
       North star: tile = fixed height, stream = flex:1 (grows to fill remaining).
       Panel has NO vertical scroll — content fits via min-height tiers.
       To revert: Restore overflow-y:auto + previous flex settings. */
    .info-panel:has(.info-layout-tile),
    .info-panel.info-panel-r3 {
        padding: 0;
        padding-bottom: 0;
        min-height: unset;
        max-height: none;
        gap: 0;
        display: flex;
        flex-direction: column;
        flex: 1;
        /* NO overflow-y — content must fit within max-height constraint */
    }
    /* END CLEAN-FIX-C8-VR-INFO-STREAM */

    /* Layout tile — NO border (R3 removed outline effect) */
    .info-layout-tile {
        width: 100%;
        background: var(--white);
        position: relative;
        overflow: hidden;
        display: flex;
        flex-direction: column;
        /* START CLEAN-FIX-P5-S7A-V3-TILE-SHADOW
           Accent shadow on info layout tile. --accent-rgb cascades from #projectN root.
           Higher opacity (0.14) than subtitle (0.12) for visual hierarchy — tile is the primary info surface.
           To revert: Delete this box-shadow declaration between START/END markers. */
        box-shadow: 0 0 24px rgba(var(--accent-rgb, 121, 126, 128), 0.28);
        /* END CLEAN-FIX-P5-S7A-V3-TILE-SHADOW */
    }

    /* CLEAN-FIX-C8-VR-INFO-STREAM: Tile uses min-height (north star: 300px fixed).
       Using min-height instead of fixed height so P1/P6 (7 categories) don't clip.
       Per-tier overrides in B5/B6/B7 blocks below.
       To revert: Change flex back to 0 0 auto, height: auto, remove min-height. */
    .info-panel.info-panel-r3 .info-layout-tile,
    .info-panel:has(.info-layout-tile) .info-layout-tile {
        flex: 0 0 auto;
        min-height: 240px;                             /* 40×6n — B5 default, tiers override */
        overflow: hidden;
    }

    /* Content container — flex grows, left padding for baseline track */
    /* CLEAN-FIX-C8-VR-INFO-STREAM: Base padding is B7 (comfortable) value.
       B5/B6 tier overrides are BELOW this rule to win by source order.
       Previously B5/B6 blocks were above this rule and lost the cascade. */
    .info-layout-content {
        flex: 1;
        padding: 24px 24px 24px 42px;              /* 7×6n left for baseline — B7 default */
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        gap: 0;
        position: relative;
    }

    /* B5 COMPACT (<700px height, e.g. iPhone SE): reduced padding for max stream space */
    @media (max-height: 699px) {
        .info-layout-content { padding: 12px 12px 12px 36px; }
        .info-layout-content::before { left: 18px; top: 12px; bottom: 12px; }
        .info-lv-subtitle, .info-lv-impact, .info-lv-tags { padding-top: 6px; padding-bottom: 6px; }
        .info-element-divider { margin: 3px 0; }
    }

    /* B6 STANDARD (700-799px height, e.g. iPhone 14): medium padding */
    @media (min-height: 700px) and (max-height: 799px) {
        .info-layout-content { padding: 18px 18px 18px 42px; }
        .info-layout-content::before { left: 24px; top: 18px; bottom: 18px; }
        .info-lv-subtitle, .info-lv-impact, .info-lv-tags { padding-top: 9px; padding-bottom: 9px; }
        .info-element-divider { margin: 6px 0; }
    }

    /* B7 COMFORTABLE (≥800px height): full padding — matches base values above */

    /* Vertical baseline (CSS ::before) — 1px accent line aligned with notch-nodes */
    .info-layout-content::before {
        content: '';
        position: absolute;
        left: 24px;                                 /* 4×6n — B7 default, aligns with notch at 42px-18px=24px */
        top: 24px;
        bottom: 24px;
        width: 1px;
        background: var(--active-accent, var(--current-accent));
        opacity: 0.3;
        z-index: 1;
    }

    /* CLEAN-FIX-C8-VR-INFO-STREAM: B5/B6 ::before overrides — MUST be AFTER base above
       Shifts baseline to intersect notch-nodes at compact/standard padding.
       B5: content padding-left 36px, notch -18px → baseline at 18px
       B6: content padding-left 42px, notch -18px → baseline at 24px (same as B7) */
    @media (max-height: 699px) {
        .info-layout-content::before { left: 18px; top: 12px; bottom: 12px; }
    }
    @media (min-height: 700px) and (max-height: 799px) {
        .info-layout-content::before { left: 24px; top: 18px; bottom: 18px; }
    }

    /* Element base — symmetric padding */
    .info-lv-subtitle,
    .info-lv-impact,
    .info-lv-tags {
        position: relative;
        padding: 12px 0;                            /* 2×6n symmetric (iframe:4103) */
    }

    /* CLEAN-FIX-C8-VR-INFO-STREAM: Info tab typeface assignments
       Subtitle body + Impact body → --font-primary (Chivo Mono)
       Subtitle <strong> + Impact <strong> → --font-secondary (Helvetica Neue), bold weight
       To revert: Change font-family back to var(--font-secondary) for both elements. */

    /* Subtitle — border-top accent, primary typeface body */
    .info-lv-subtitle {
        font-family: var(--font-primary);
        font-size: var(--font-size-small);           /* 0.8rem = 12.8px — matches north star computed size */
        font-weight: var(--font-weight-medium);
        color: var(--darkest);
        border-top: 1px solid var(--active-accent, var(--current-accent));
    }

    /* Subtitle <strong> — secondary typeface, bold weight, inherits color */
    .info-lv-subtitle strong {
        font-family: var(--font-secondary);
        font-weight: var(--font-weight-bold);        /* 700 */
    }

    /* Impact — 6px border-left accent, primary typeface body */
    .info-lv-impact {
        font-family: var(--font-primary);
        font-size: var(--font-size-small);           /* 0.8rem = 12.8px — matches north star computed size */
        font-weight: var(--font-weight-medium);
        border-left: 6px solid var(--active-accent, var(--current-accent));
        padding-left: var(--spacing-18);             /* 3×6n (iframe:4127 G8 shift) */
        line-height: 1.4;
        color: var(--darkest);
    }

    /* Impact <strong> — secondary typeface, bold weight (matches subtitle strong), accent color unchanged */
    .info-lv-impact strong,
    .info-lv-impact .highlight {
        font-family: var(--font-secondary);
        font-weight: var(--font-weight-bold);        /* 700 — matches subtitle strong weight */
        color: var(--active-accent, var(--current-accent));
    }

    /* Tags — flex wrap */
    .info-lv-tags {
        display: flex;
        flex-wrap: wrap;
        gap: 6px;                                    /* 1×6n (iframe:4142) */
        align-items: flex-start;
    }

    .info-lv-tag {
        font-family: var(--font-primary);
        font-size: var(--font-size-specialized);     /* 0.65rem = 10.4px (design system token) */
        font-weight: var(--font-weight-medium);
        text-transform: uppercase;
        color: var(--black);
        background: var(--lightest);
        border-left: 2px solid var(--active-accent, var(--current-accent));
        padding: var(--spacing-6, 6px) var(--spacing-12, 12px);  /* 1×6n / 2×6n — 6n-compliant (north star uses 4px/10px, adjusted for design system) */
        border-radius: 3px;
    }

    /* Notch node — accent dot on baseline */
    .notch-node {
        position: absolute;
        left: -18px;                                 /* 42px padding - 24px baseline = 18px (iframe:4162) */
        top: 50%;
        transform: translate(-50%, -50%);
        width: 6px;
        height: 6px;
        border-radius: 50%;
        background: var(--active-accent, var(--current-accent));
        z-index: 4;
        pointer-events: none;
    }

    /* Impact notch — compensate for 6px border-left */
    .info-lv-impact .notch-node {
        left: -24px;                                 /* 18px + 6px border (iframe:4175) */
    }

    /* Connector lines (CSS ::after) */
    .info-lv-subtitle::after,
    .info-lv-tags::after {
        content: '';
        position: absolute;
        left: -18px;
        top: 50%;
        width: 18px;                                 /* 3×6n gap (iframe:4186) */
        height: 1px;
        background: var(--active-accent, var(--current-accent));
        opacity: 0.3;
        transform: translateY(-50%);
        z-index: 2;
    }

    /* Impact connector — compensate for 6px border-left */
    .info-lv-impact::after {
        content: '';
        position: absolute;
        left: -24px;
        top: 50%;
        width: 24px;                                 /* 4×6n (iframe:4200) */
        height: 1px;
        background: var(--active-accent, var(--current-accent));
        opacity: 0.3;
        transform: translateY(-50%);
        z-index: 2;
    }

    /* Divider — sibling element between R3 elements */
    .info-element-divider {
        height: 1px;
        background: var(--light);
        margin: 6px 0;                               /* 1×6n (iframe:4213) */
        flex-shrink: 0;
    }

    /* CLEAN-FIX-C8-VR-INFO-STREAM: B5/B6 element overrides — MUST be AFTER base rules above
       to win cascade. Base padding: 12px 0, divider margin: 6px 0 (B7 comfortable defaults).
       B5/B6 reduce these for compact/standard screens to maximize stream space.
       To revert: Remove these two @media blocks. */
    @media (max-height: 699px) {
        .info-lv-subtitle, .info-lv-impact, .info-lv-tags { padding-top: 6px; padding-bottom: 6px; }
        .info-element-divider { margin: 3px 0; }
        .notch-node { left: -18px; }
        .info-lv-impact .notch-node { left: -24px; }
    }
    @media (min-height: 700px) and (max-height: 799px) {
        .info-lv-subtitle, .info-lv-impact, .info-lv-tags { padding-top: 9px; padding-bottom: 9px; }
        .info-element-divider { margin: 6px 0; }
    }

    /* R2 deprecated elements — hidden for cleanup */
    .info-vertical-baseline { display: none; }
    .notch-connector { display: none; }

    /* --- Stream container (horizontal asset scroll at bottom of info) ---
       Ported from: iframe lines 4663-4776 (CLEAN-FIX-V8-G7-STREAM-CONTAINER) */

    /* CLEAN-FIX-C8-VR-INFO-STREAM: Stream grows to fill remaining space below tile.
       North star model: flex:1 with per-tier min-heights (B5=60, B6=72, B7=90).
       To revert: Change flex to 0 0 auto, add height: 90px. */
    .info-panel.info-panel-r3 .fe-info-stream-container,
    .info-panel:has(.info-layout-tile) .fe-info-stream-container {
        flex: 1;
        min-height: 60px;                            /* 10×6n floor — B5/B6/B7 override */
        position: relative;
    }

    .fe-info-stream-container {
        width: 100%;
        margin: 0;
        overflow: hidden;
        background: linear-gradient(to bottom,
            rgba(var(--lightest-rgb), var(--opacity-strong)),
            color-mix(in srgb, var(--active-accent, var(--current-accent)) 3%, rgba(var(--lightest-rgb), var(--opacity-strong))));
        border-top: 1px solid color-mix(in srgb, var(--active-accent, var(--current-accent)) 50%, transparent);
        clip-path: polygon(0% 6px, 6px 0%, calc(100% - 6px) 0%, 100% 6px, 100% 100%, 0% 100%);
    }

    @keyframes fe-stream-scroll {
        0% { transform: translate3d(0, 0, 0); }
        100% { transform: translate3d(-50%, 0, 0); }
    }

    .fe-stream-track {
        position: absolute;
        top: 6px;
        left: 12px;
        right: 12px;
        bottom: 6px;
        display: flex;
        gap: 42px;                                   /* 7×6n (iframe:4704) */
        align-items: center;
        animation: fe-stream-scroll var(--stream-duration, 30s) linear infinite;
        will-change: transform;
        backface-visibility: hidden;
    }

    .fe-stream-asset {
        flex-shrink: 0;
        height: 100%;
        border: 1px solid var(--light);
        border-radius: 1px;                          /* CLEAN-FIX-C8-VR-INFO-STREAM: was 3px, cut to 1/4 per user feedback */
        overflow: hidden;
        background: var(--white);
    }

    .fe-stream-asset img,
    .fe-stream-asset video {
        height: 100%;
        width: auto;
        object-fit: contain;
        display: block;
    }

    @media (prefers-reduced-motion: reduce) {
        .fe-stream-track {
            animation: none;
            transform: none;
        }
        .fe-info-stream-container {
            overflow-x: auto;
        }
    }

    /* Per-project border radius (brutalist vs iPhone mockup) */
    .fe-info-stream-container.info-av-1 .fe-stream-asset,
    .fe-info-stream-container.info-av-5 .fe-stream-asset,
    .fe-info-stream-container.info-av-6 .fe-stream-asset {
        border-radius: 0;
    }

    .fe-info-stream-container.info-av-2 .fe-stream-asset,
    .fe-info-stream-container.info-av-3 .fe-stream-asset,
    .fe-info-stream-container.info-av-4 .fe-stream-asset {
        border-radius: 3px;                          /* CLEAN-FIX-C8-VR-INFO-STREAM: was 12px, cut to 1/4 per user feedback */
    }

    .fe-info-stream-container.info-av-2 .fe-stream-asset img,
    .fe-info-stream-container.info-av-2 .fe-stream-asset video,
    .fe-info-stream-container.info-av-3 .fe-stream-asset img,
    .fe-info-stream-container.info-av-3 .fe-stream-asset video,
    .fe-info-stream-container.info-av-4 .fe-stream-asset img,
    .fe-info-stream-container.info-av-4 .fe-stream-asset video {
        border-radius: inherit;
    }
    /* END CLEAN-FIX-C8-P2B-F3-INFO-R3 — Base R3 + Stream CSS */

    /* CLEAN-FIX-C8-VR-TIMELINE-CLASSES — RELOCATED 2026-04-16 by CLEAN-FIX-P5-S6.5-TIMELINE-820-SCOPE
       The timeline-bar-* rule block was physically moved out of this Step 2d
       @media (max-width: 819px) wrapper to global scope, so rules apply at
       all widths (≥820px in particular, where they were absent and caused
       endpoint label clipping/collisions and phase label flow-collapse).
       See CLEAN-FIX-P5-S6.5-TIMELINE-820-SCOPE after the Step 2d closer below
       for the relocated block and full rationale.
       To revert the relocation: `git revert` the commit that shipped
       CLEAN-FIX-P5-S6.5-TIMELINE-820-SCOPE. Single atomic revert restores this
       block at its original location (L2976-3085 pre-relocation) and removes
       the global-scope copy. */

    /* --- Overview Content: REMOVED .fe-overview-section-title + .fe-overview-paragraph ---
       Replaced by .overview-content.enhanced typography system (CLEAN-FIX-C8-P2B-VF-OVERVIEW-ENHANCED-TYPO).
       To restore: re-add .fe-overview-section-title and .fe-overview-paragraph rules. */

} /* END @media (max-width: 819px) — Step 2d */

/* END CLEAN-FIX-C8-P2D-FE-CONTENT */


/* START CLEAN-FIX-P5-S6.5-TIMELINE-820-SCOPE
   Relocates CLEAN-FIX-C8-VR-TIMELINE-CLASSES out of @media (max-width: 819px)
   Step 2d wrapper so timeline-bar-* rules apply at all widths (≥820px in
   particular).

   Root cause (identified 2026-04-16): The original port at ca22a06 swept the
   desktop-intent timeline rules into the mobile Step 2d block. Result:
   .timeline-bar-* layout rules were scoped to ≤819px, leaving 820+ with
   only inline JS styles (partial position:absolute + left:X%). Phase labels
   and endpoint labels collapsed to document flow at 820+ or misaligned
   against the track line.

   Symptom evidence at 820×1180 (tablet portrait):
   - Endpoint labels clip at viewport edges (e.g., "wk.0" clips to "k.0" on
     left; "wk.5" truncates to "wk." on right).
   - Vertical endpoint prefix/value labels (`.timeline-bar-endpoint-prefix`,
     `.timeline-bar-endpoint-value`) render as plain text "wk0wk5" without
     positioning (they're mobile-only DOM but the JS generates them at all
     widths; mobile styles keep them positioned, desktop had no rule to
     suppress them).
   - Phase labels (ph.1 / ph.2 / ph.3 + CONFRONTATION/CALIBRATION/
     TRANSCENDENCE) partially rendered due to inline `left: X%` styles but
     their transform: translateX(-50%) was missing, misaligning from the
     track node centers.

   Fix: Move the entire CLEAN-FIX-C8-VR-TIMELINE-CLASSES block (including
   @keyframes phase-node-pulse) out of the Step 2d wrapper to global scope.
   The inner CLEAN-FIX marker is preserved; only source location changes.
   Added: one `@media (min-width: 768px)` rule hiding the vertical prefix/
   value labels at desktop (preventing double-label rendering alongside
   horizontal endpoint labels at ≥768px). Breadcrumb comment left at
   original Step 2d location documenting the move.

   Mobile (≤767px) behavior unchanged: the existing CLEAN-FIX-8A-B2-PROJCOL-PORT
   block at L95-147 still styles vertical labels and hides horizontal labels
   at phone sizes via its own @media (max-width: 767px) scope with higher
   specificity (`.inline-timeline .timeline-bar-endpoint-label`).

   Dependencies: None new. Reuses --active-accent, --current-accent,
   --accent-rgb, --warm, --dark, --darkest, --white, --lightest tokens from
   v3-design-system.css. Keyframe phase-node-pulse referenced by animation
   rule inside this block, same scope.

   Reversibility: Search CLEAN-FIX-P5-S6.5-TIMELINE-820-SCOPE and delete
   between START/END markers. Restore the inner CLEAN-FIX-C8-VR-TIMELINE-
   CLASSES block back inside the Step 2d wrapper at its pre-relocation
   location (L2976-3085 original, now a breadcrumb comment). Git revert on
   this commit does both operations atomically.

   Verify:
   - 820×1180 portrait (MD) → .inline-timeline renders 48px tall with
     --lightest background; endpoint nodes at left:18px / right:18px;
     horizontal endpoint labels top:4px positioned correctly with JS-inline
     transform(-50%/50%); phase labels positioned via transform: translateX
     (-50%) along track line; CONFRONTATION/CALIBRATION/TRANSCENDENCE labels
     at bottom:4px centered on their phase nodes.
   - 992×800 (LG min), 1199×800 (LG max), 1200×900 (XL) → same behavior.
   - 767×1024 (SM) → mobile vertical labels kick in via CLEAN-FIX-8A-B2-
     PROJCOL-PORT; horizontal labels hidden; vertical prefix/value
     positioned per mobile block; this relocation doesn't affect mobile.
   - ≥768px at any viewport → vertical prefix/value labels hidden
     (display: none) via the @media (min-width: 768px) rule added below.
*/

/* START CLEAN-FIX-C8-VR-TIMELINE-CLASSES — Base timeline styles (ported from north star)
   Root cause: Previous .fe-timeline-* classes didn't match B2 CSS selectors.
   New JS generates .timeline-bar-* classes matching north star DOM (iframe lines 2158-2264).
   Relocated 2026-04-16 out of @media (max-width: 819px) Step 2d wrapper
   (see outer CLEAN-FIX-P5-S6.5-TIMELINE-820-SCOPE for move rationale).
   To revert: Restore .fe-timeline-* rules, revert JS in populateHeaderSecondary. */

/* Timeline container — 48px (8×6n), full-bleed with negative margins */
.inline-timeline {
    width: calc(100% + 24px);
    height: 48px;                                  /* 8×6n (north star R4.3.1) */
    background: var(--lightest);
    display: flex;
    align-items: center;
    position: relative;
    margin-left: -12px;
    margin-right: -12px;
    padding: 0 30px;                               /* 5×6n */
    overflow: visible;
}

/* Track line — accent-colored horizontal bar */
.timeline-bar-track {
    position: absolute;
    top: 50%;
    left: 18px;                                    /* 3×6n */
    right: 18px;
    height: 2px;
    background: var(--active-accent, var(--current-accent));
    transform: translateY(-50%);
}

/* Endpoint nodes (dots) */
.timeline-bar-endpoint-node {
    position: absolute;
    top: 50%;
    width: 6px;                                    /* 1×6n */
    height: 6px;
    border-radius: 50%;
    background: var(--dark);
}
.timeline-bar-endpoint-node.start { left: 18px; transform: translate(-50%, -50%); }
.timeline-bar-endpoint-node.end { right: 18px; transform: translate(50%, -50%); }

/* Endpoint labels (desktop horizontal — hidden at <768px by B2 CSS) */
.timeline-bar-endpoint-label {
    font-family: var(--font-primary);
    font-size: var(--font-size-specialized);
    font-weight: 400;
    color: var(--warm);
    text-transform: lowercase;
    white-space: nowrap;
    letter-spacing: 0.5px;
    line-height: 1;
    position: absolute;
    top: 4px;
}

/* Endpoint label anchoring by side — replaces legacy JS inline
   `transform: translateX(±50%)` which caused clipping at narrow desktops.
   Left-align at start anchor, right-align at end anchor. Paired with
   CLEAN-FIX-P5-S6.5-TIMELINE-LABEL-CLIP in V3ExpandedController.js. */
.timeline-bar-endpoint-label.start { left: 18px; }   /* 3×6n */
.timeline-bar-endpoint-label.end   { right: 18px; }  /* 3×6n */

/* Phase nodes (hollow circles with accent border) */
.timeline-bar-phase-node {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--white);
    border: 2px solid var(--active-accent, var(--current-accent));
    position: absolute;
    top: 50%;
    transform: translate(-50%, -50%);
    z-index: 3;
}

/* Phase top labels (phase number) */
.timeline-bar-phase-label-top {
    position: absolute;
    top: 4px;
    transform: translateX(-50%);
    font-family: var(--font-primary);
    font-size: var(--font-size-specialized);
    font-weight: 500;
    color: var(--dark);
    white-space: nowrap;
    text-transform: lowercase;
    line-height: 1;
}

/* Phase bottom labels (phase name) */
.timeline-bar-phase-label-bottom {
    position: absolute;
    bottom: 4px;
    transform: translateX(-50%);
    font-family: var(--font-secondary);
    font-size: var(--font-size-specialized);
    font-weight: 700;
    color: var(--darkest);
    white-space: nowrap;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

/* Phase node pulse animation (9s cycle, staggered per data-phase-index) */
.inline-timeline .timeline-bar-phase-node {
    animation: phase-node-pulse 9s ease-in-out infinite;
}
.inline-timeline .timeline-bar-phase-node[data-phase-index="1"] { animation-delay: 0s; }
.inline-timeline .timeline-bar-phase-node[data-phase-index="2"] { animation-delay: 3s; }
.inline-timeline .timeline-bar-phase-node[data-phase-index="3"] { animation-delay: 6s; }

@keyframes phase-node-pulse {
    0%, 20% { transform: translate(-50%, -50%) scale(1); box-shadow: none; }
    10%     { transform: translate(-50%, -50%) scale(1.6); box-shadow: 0 0 6px rgba(var(--active-accent-rgb, 0,0,255), 0.4); }
}
/* END CLEAN-FIX-C8-VR-TIMELINE-CLASSES */

/* Desktop-only: suppress vertical endpoint prefix/value labels (mobile-only layout).
   The JS generates these at all widths; without this rule they render as
   unstyled plain text at ≥768px alongside the horizontal endpoint labels. */
@media (min-width: 768px) {
    .inline-timeline .timeline-bar-endpoint-prefix,
    .inline-timeline .timeline-bar-endpoint-value {
        display: none;
    }
}
/* END CLEAN-FIX-P5-S6.5-TIMELINE-820-SCOPE */


/* START CLEAN-FIX-P5-S7A-V2-TYPE-STRESS
   Tighter letter-spacing at desktop widths (≥992px) for typographic stress.
   End-of-file placement ensures cascade win over earlier 0.5px/1px decls in responsive breakpoints.
   To revert: Search CLEAN-FIX-P5-S7A-V2-TYPE-STRESS, delete START→END block. */
@media (min-width: 992px) {
    .project-header h1,
    .project-subtitle,
    .project-impact,
    .overview-content-vertical h3 {
        letter-spacing: -0.02em;
    }
}
/* END CLEAN-FIX-P5-S7A-V2-TYPE-STRESS */

/* START CLEAN-FIX-P5-S7E1-V8-820-SCALING
   V8 Proportional Info Scaling — 820px tier (1.1x).
   Targets: .project-title-expanded h2, .project-subtitle, .project-impact.
   Activates at the C.8–C.11 special desktop boundary (820px, not 992px — per P5-S3).

   Scope revision from blueprint: .v8-tag padding rule SKIPPED — selector does not
   exist in src/v3 as of 2026-04-13 audit. Avoids adding CSS for non-existent
   selector (anti-bloat). Will be added in a future marker if/when the class ships.

   Defensibility: Scales info typography 1.1x to match visual weight of hero area
   at iPad Air+ widths. Uses calc() off existing design-system tokens
   (--font-size-super-huge, --font-size-standard) — no magic numbers, no new
   tokens. Sibling to P5-S7A-V2-TYPE-STRESS (end-of-file placement ensures cascade
   win over earlier responsive breakpoint declarations).

   Evidence: Step 2 Cat C aha decision (15/16 accepted, @ui-ninja reviewed,
   commit `643be6a`); canonical blueprint at
   ~/.claude/plans/functional-cuddling-flamingo.md Part 2; revised execution
   plan at ~/.claude/plans/synchronous-herding-valley.md Step 7E-1.

   If not effective: (1) Check cascade order — v3-project-columns-responsive.css
   must load AFTER project-column-styles.css in index.html. (2) Verify
   --font-size-super-huge and --font-size-standard tokens resolve in devtools.
   (3) Confirm 820px media query fires via diagnostic console.log in
   V3ExpandedController.transitionToExpanded() (tag: [V3-P5-S7E1]).
   (4) Inspect .project-title-expanded h2 computed font-size — expected 79.2px.

   Stopping condition: If MD max 991×1200 overflows vertically after this lands,
   ship P5-S7E1-4A-DELTA marker (Tier 1 padding compression @ max-height:900px)
   as a SEPARATE NEW marker — do NOT mutate P5-S4A-VERTICAL-FIT. If the delta
   cycle cannot resolve overflow, pause and decide: (a) defer 7E-1 entirely,
   (b) scale subtitle/impact at 1.05x instead of 1.1x (keep h2 at 1.1x).

   Verification: Pre-flight at MD max 991×1200 (primary), LG min 992×700,
   XL min 1200×800, 1920×1080. Step 4A Tier 1/Tier 2 vertical-fit markers
   must still engage at ≤900px / ≤720px heights.

   To revert: Search CLEAN-FIX-P5-S7E1-V8-820-SCALING, delete everything
   between START and END markers. */
/* MODIFY-IN-PLACE 2026-05-05 (annotation V-S13-V8-GATE-REFINEMENT): media query
   gate tightened from `min-width: 820px` to `min-width: 1200px` so V8 typography
   1.1x scaling fires only at XL+, not at MD-larger 820-991 OR LG 992-1199.
   Per user direction "viewport HEIGHT should be the key factor in strategy
   considerations" + explicit @ui-ninja-confirmed step-down on `.project-subtitle`
   children at MD-larger 991×900. Per Phase III modify-in-place precedent (Chunks
   F + G + LG-MACRO-H-PER-PROJECT-ACCENT). 3-agent ship-readiness review 2026-05-05
   (Plan + code-review-analyst + ui-ninja) all green-light for this gate refinement.

   Effect at MD-larger 991×900: subtitle/impact return from 15.84px (1.1× scaled)
   to 14.4px (base --font-size-standard); h2 returns from 79.2px to 72px
   (--font-size-super-huge). User-requested step-down 1 design-system size.

   Effect at LG 992-1199: same step-down. Note: V4 at line 3509 already overrides
   `.project-impact` font-size at LG 820-1199 × ≤900h via clamp(14px, 1.5vw, 16px)
   `!important`, so Layer 1 affects `.project-subtitle` + `.project-title-expanded h2`
   only at LG (impact already controlled by V4). Aesthetic verdict: 5x title-to-body
   ratio preserves brutalist hierarchy per ui-ninja review.

   Effect at XL 1200+: unchanged (1.1× scaling preserved per V8 design intent
   "iPad Air+ visual hierarchy").

   To revert this gate refinement only: change `min-width: 1200px` back to
   `min-width: 820px`. */
@media (min-width: 1200px) {
    .project-title-expanded h2 {
        font-size: calc(var(--font-size-super-huge) * 1.1);
    }
    .project-subtitle,
    .project-impact {
        font-size: calc(var(--font-size-standard) * 1.1);
    }
}
/* END CLEAN-FIX-P5-S7E1-V8-820-SCALING */

/* START CLEAN-FIX-P5-S7C2B-M2-COORD-ECHO
   M2 — XL radiating coord-point echo on active column (Phase 5 aha,
   2026-04-14 scope lock, redefined from "cascading numbered coord points"
   to "radiating coord-point echo" after V7 landed as CSS gradients).

   Adds 2 concentric echo rings via `::before` and `::after` on the
   existing `.coord-point` element when its parent column is active at XL.
   On activation, the rings expand outward (scale 0.5 → 4) and fade
   (opacity 1 → 0) over 900ms with 60ms stagger — a radar/sonar ping
   that reads as the coordinate being "plotted" in the Brutalist
   surveyor/blueprint metaphor.

   Why 2 rings (not 3):
   The first-pass plan included a third ring via a keyframe on the
   `.coord-point` element itself. Code-review flagged that
   `.coords-system.accessing .coord-point` already has `animation:
   coordPulse 2s ease-in-out infinite` (line 422) and
   `animation: blink 1s infinite` (line ~1486). Adding a third
   animation on the parent during the `.accessing` state would
   collide — CSS animation shorthand would override the existing
   animations. Two rings on `::before`/`::after` avoid this entirely
   since pseudo-elements have their own animation stacks.

   `inset: -12px` (not `inset: 0`):
   `.coord-point` is only 6px × 6px (line 371-372). With `inset: 0`,
   the pseudo-elements start at 6px × 6px — too small for visible
   echoing (scale(4) = 24px, barely visible). `inset: -12px` starts
   the pseudo-element at 30px × 30px (6 + 12 + 12 = 30 = 5×6n). At
   scale(4) the ring reaches 120px diameter — clearly visible and
   proportional to the coords-system box (~120px).

   Per-project accent:
   `rgba(var(--accent-rgb), 0.6)` — consumes the per-project accent
   token cascaded from `:root` via 7B.0b hoist. Border color tracks
   P1 warm / P2 blue / P3 pink / P4 purple / P5 darkblue / P6 cyan.

   XL-only gate:
   At LG (992-1199) the active column is narrower and the 120px ring
   diameter at scale(4) would extend beyond the column bounds, getting
   clipped and looking cramped. XL (1200+) gives enough room for the
   echo to breathe outward without hitting the column edge.

   `animation-fill-mode: forwards`:
   Keeps the pseudo-elements at their final state (opacity: 0, scale: 4)
   after the animation ends. Without `forwards`, they would snap back
   to the starting state (visible ring at scale 0.5) which looks wrong.

   Reduced-motion suppression:
   Local `@media (prefers-reduced-motion: reduce)` block inside the
   marker suppresses the animation entirely and hides the pseudo-
   elements (`animation: none; opacity: 0`). Matches 7B.0a CSS gate
   baseline.

   Dependencies: 7B.0b `--accent-rgb` :root hoist (388da45).
   Blocks: Nothing downstream (M4 magnetic snap was dependent on V7
   dot positions which are now removed; M4 to be reassessed).

   Reversibility: Search CLEAN-FIX-P5-S7C2B-M2-COORD-ECHO and delete
   everything between START and END markers. Single file, single media
   block + keyframe + reduced-motion suppression.

   Verify:
   - 1200×800 (XL min) → activate a column, single `.coord-point`
     pings out with TWO concentric rings expanding outward over ~900ms.
     Ring diameter reaches ~120px at peak. 60ms stagger between the
     two rings creates a "ripple" read.
   - 1920×1080 (XL wide) → same echo, more room to breathe.
   - Cycle P1 → P6 at XL → ring color tracks per-project accent.
   - 1199×800 (LG max) → NO echo (XL gate cuts off).
   - Echo does NOT fire during `.accessing` state on its own —
     coordPulse animates the parent, echo animates the children,
     both are independent stacks. If both states overlap briefly
     during activation, the visual compositing is coherent (parent
     pulses, children echo — reads as "double emphasis").
   - DevTools → Rendering → Emulate prefers-reduced-motion: reduce
     → no rings, no animation.

   Verification surface: `test-responsive-production.html` or
   `index.html` directly. */
@media (min-width: 1200px) {
    .project-column.active .coord-point::before,
    .project-column.active .coord-point::after {
        content: '';
        position: absolute;
        inset: -12px;
        border: 1px solid rgba(var(--accent-rgb, 121, 126, 128), 0.6);
        border-radius: 50%;
        pointer-events: none;
        animation: coord-ping 900ms ease-out forwards;
    }
    .project-column.active .coord-point::after {
        animation-delay: 60ms;
    }
}
@keyframes coord-ping {
    0%   { transform: scale(0.5); opacity: 1; }
    100% { transform: scale(4);   opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
    .project-column.active .coord-point::before,
    .project-column.active .coord-point::after {
        animation: none;
        opacity: 0;
    }
}
/* END CLEAN-FIX-P5-S7C2B-M2-COORD-ECHO */


/* START CLEAN-FIX-P5-S7C2B-M2-SET1-H5-SUPERSEDE
   Supersedes M2 coord-ping echo (CLEAN-FIX-P5-S7C2B-M2-COORD-ECHO,
   commit edc6a9d) with H-5 Ripple Wave on .coord-point::before.
   Extends scope to include mobile active state (M2 was XL-desktop only).

   Design decision 2026-04-16: User upgraded Set 1 coord-point pulse
   from M2 (2 scale-expanding rings) to H-5 Ripple Wave (3 concentric
   box-shadow rings). Tier: Heavy. Cadence: 2400ms linear infinite.
   Applies on BOTH desktop expanded (XL) AND mobile active (single-
   column layout has room for ripple to breathe). Excludes MD/LG
   tablet (768-1199) where the multi-column layout crams the ripple
   against column edges — same cramping concern that originally gated
   M2 to XL-only.

   Strategy: Additive override. The M2 block above remains intact for
   revert traceability. CSS cascade (same specificity, later source
   wins) supersedes M2's scale-rings with H-5 box-shadow-ripple on
   .coord-point::before; M2's ::after is suppressed via display:none
   since H-5 uses multi-layered box-shadow on a single element.

   H-5 keyframe (coord-ripple-wave) derived from test-pulse-variations.html
   line 139 heavy-ripple-wave. Three concentric box-shadow rings at
   0/18/36/54px cascade with opacity fades. Per-project color via
   --accent-rgb token chain (7B.0b :root hoist + 7A per-project overrides).

   Media gating:
   - @media (max-width: 767px) OR (min-width: 1200px) → H-5 ripple fires
   - @media (min-width: 768px) and (max-width: 1199px) → pseudos hidden
   - @media (prefers-reduced-motion: reduce) → ripple suppressed

   Dependencies: 7B.0b --accent-rgb :root hoist (commit 388da45) +
   7A per-project --accent-rgb overrides. 7B.0a reduced-motion baseline
   gate (dc4765d).

   Reversibility: Search CLEAN-FIX-P5-S7C2B-M2-SET1-H5-SUPERSEDE and
   delete everything between START and END markers. M2 coord-ping echo
   above will resume active behavior at XL desktop only (restoring
   commit edc6a9d baseline). No other files affected.

   Verify:
   - 1200×800 (XL desktop, any active column) → H-5 ripple fires from
     .coord-point ::before, 3 rings expanding outward 0→54px over
     2400ms at cascading opacities (0.6 → 0 / 0.4 → 0 / 0.2 → 0).
   - 375×667 (mobile XS, active column) → same ripple fires.
   - 768×1024 (MD tablet, active column) → NO ripple (pseudos hidden).
   - 1199×800 (LG max desktop, active column) → NO ripple.
   - Cycle P1 → P6 at XL → ripple color tracks per-project accent.
   - DevTools → Rendering → Emulate prefers-reduced-motion: reduce
     → no ripple, no box-shadow.

   Verification surface: test-responsive-production.html or direct
   viewport sizing on index.html. */

/* XL desktop + Mobile - pulse via ::before with H-3 Glow Burst (R4-PHASE-III-PULSE-REDO 2026-04-28) */
@media (max-width: 767px), (min-width: 1200px) {
    .project-column.active .coord-point::before {
        content: '';
        position: absolute;
        inset: 0;
        border: none;                       /* override M2 border (scale rings) */
        border-radius: 50%;
        pointer-events: none;
        /* R4-PHASE-III-PULSE-REDO 2026-04-28: SET1 H-5 Ripple Wave (coord-ripple-wave 2400ms linear)
           superseded by H-3 Glow Burst per Phase II Section 4.5 user-decided pulse mapping.
           Tier 1 Heavy. Source: test-pulse-variations.html line 122. Per-project accent via
           var(--accent-rgb) consumed in box-shadow (with warm-rgb fallback). */
        animation: heavy-glow-burst 3000ms cubic-bezier(0.4, 0, 0.6, 1) infinite;
    }
    /* Suppress M2's ::after - H-3 uses single ::before with scale + box-shadow */
    .project-column.active .coord-point::after {
        display: none;
    }
}

/* MD/LG tablet (768-1199) - suppress pseudos entirely (glow burst would crop in multi-column layout) */
@media (min-width: 768px) and (max-width: 1199px) {
    .project-column.active .coord-point::before,
    .project-column.active .coord-point::after {
        display: none;
    }
}

/* R4-PHASE-III-PULSE-REDO 2026-04-28: keyframe body replaced from coord-ripple-wave (3 concentric
   rings 0->18->36->54px) to H-3 Glow Burst (scale 1->1.3 + box-shadow burst up to 36px) per user
   decision. Renamed canonical heavy-glow-burst to match test-pulse-variations.html source-of-truth. */
@keyframes heavy-glow-burst {
    0%   { transform: scale(1);   box-shadow: 0 0  0   rgba(var(--accent-rgb, 121, 126, 128), 0); }
    25%  { transform: scale(1.1); box-shadow: 0 0 12px rgba(var(--accent-rgb, 121, 126, 128), 0.8); }
    75%  { transform: scale(1.3); box-shadow: 0 0 24px rgba(var(--accent-rgb, 121, 126, 128), 1),
                                               0 0 36px rgba(var(--accent-rgb, 121, 126, 128), 0.4); }
    100% { transform: scale(1);   box-shadow: 0 0  0   rgba(var(--accent-rgb, 121, 126, 128), 0); }
}

@media (prefers-reduced-motion: reduce) {
    .project-column.active .coord-point::before {
        animation: none;
        box-shadow: none;
    }
}
/* END CLEAN-FIX-P5-S7C2B-M2-SET1-H5-SUPERSEDE */


/* ============================================================================
   START CLEAN-FIX-P5-S6.5c-A3-V4 (2026-04-21; scope corrected 2026-04-22)
   ============================================================================
   V4 — Impact Inline (subtitle + impact side-by-side at MD Max 820-1199)

   Source: test-layout-triage-option-2a.html CSS_V4 (lines 454-469)
   Plan:   ~/.claude/plans/hi-we-are-compiled-meerkat.md Chunk 1.1
   Scope:  MD-larger desktop implementation at 820-1199 × 701-900h (MD Max).
           Height gate (max-height: 900px) added to match triage composite
           contract: triage's `final_ipad` (834×1194, ≥901h) composite does
           NOT inject V4 — only V5. So V4 must NOT fire at iPad Air height
           range, even though triage's raw CSS_V4 @media omits this gate
           (in triage, composite selection is JS-controlled; in production,
           @media self-gating replaces the composite selector).
   Intent: Reclaim vertical space in tight MD Max 991×900 viewport by flipping
           subtitle + impact from column-stacked to row-flex side-by-side.
           Fits module + overview-trigger below without clipping.

   Specificity: 0,2,0 + !important (port fidelity per plan).
   Existing baseline at project-column-styles.css:966 is 0,1,0 → V4 wins.
   Per-project #projectN .project-impact font-size (0,1,0) overridden at
   MD Max by V4's clamp(14px, 1.5vw, 16px) !important (intended).

   To revert: Search for CLEAN-FIX-P5-S6.5c-A3-V4 and delete everything
   between START and END markers.
   ============================================================================ */
@media (min-width: 820px) and (max-width: 1199px) and (max-height: 900px) {
    .project-info-column .project-subtitle-container {
        display: flex !important;
        /* Port-fidelity patch (2026-04-22): triage CSS_V4 omits flex-direction,
           but production baseline at project-column-styles.css:973 sets
           flex-direction: column. V4's stated intent ("subtitle + impact
           side-by-side") requires row direction. Added at V4's 0,2,0
           specificity (beats baseline 0,1,0) — no new !important per plan
           rule; relies on selector specificity only. */
        flex-direction: row;
        gap: 24px !important;
        align-items: flex-start !important;
    }
    .project-info-column .project-subtitle { flex: 1.2 !important; margin-bottom: 0 !important; }
    .project-info-column .project-impact {
        flex: 0.8 !important; margin: 0 !important;
        font-size: var(--font-size-standard) !important; /* V-S13-L1-EXT 2026-05-06: was clamp(14px, 1.5vw, 16px) — replaced with --font-size-standard (0.9rem = 14.4px) to recover Layer 1 design-system body-text token at LG ≤900h composites where V4 fires alone (LG-MACRO-H gates ≤800h post-MC-2..5; V4 still wins at LG 801-900h). Flattens impact from clamp's 14-16px range to consistent 14.4px standard, matching MD-larger 801-900h body-text. */
    }
    .project-info-column .project-impact .highlight { display: inline !important; }
}
/* END CLEAN-FIX-P5-S6.5c-A3-V4 */


/* ============================================================================
   START CLEAN-FIX-P5-S6.5c-A3-V5 (2026-04-22)
   ============================================================================
   V5 — Direct Vertical Compression (iPad Air only)

   Source: test-layout-triage-option-2a.html CSS_V5 (lines 471-511)
   Plan:   ~/.claude/plans/hi-we-are-compiled-meerkat.md Chunk 1.2
   Scope:  iPad Air at 820-1199 × ≥901h.
           Triage's `final_ipad` composite injects V5 ALONE (no V4/V6/V12).
           (min-height: 901px) gate added so V5 does NOT fire at MD Max
           (which gets V4 + V6 + V12 instead). Triage's raw CSS_V5 @media
           omits the gate because the composite selector in test harness
           handles scope; production has no selector layer, so self-gating
           via @media replaces it.
   Intent: Reclaim ~96px of vertical space across .project-info-column
           tier-1 padding + gap for iPad Air's 1194h viewport budget.
           User confirmed 100% clean at 834×1194, per triage comment.

   Specificity: 0,2,0 on children + 0,1,0 on container root (matches
   baseline at project-column-styles.css:911 — overrides via !important).

   To revert: Search for CLEAN-FIX-P5-S6.5c-A3-V5 and delete everything
   between START and END markers.
   ============================================================================ */
@media (min-width: 820px) and (max-width: 1199px) and (min-height: 901px) {
    .project-info-column {
        padding: 24px 30px !important;
        gap: 12px !important;
    }
    .project-info-column .project-title-expanded {
        margin-bottom: 6px !important;
    }
    .project-info-column .project-title-expanded h2 {
        line-height: 0.9 !important;
        margin: 0 !important;
    }
    .project-info-column .project-subtitle-container {
        padding: 12px 18px !important;
        margin: 0 !important;
    }
    .project-info-column .project-subtitle {
        margin: 0 0 12px 0 !important;
        line-height: 1.3 !important;
    }
    .project-info-column .project-impact {
        margin: 0 !important;
        line-height: 1.35 !important;
    }
    .project-info-column .project-module {
        margin: 12px 0 !important;
    }
    .project-info-column .work-categories {
        gap: 6px !important;
        margin: 12px 0 !important;
    }
    .project-info-column .overview-trigger {
        padding: 12px 18px !important;
        margin-top: 12px !important;
    }
}
/* END CLEAN-FIX-P5-S6.5c-A3-V5 */


/* ============================================================================
   START CLEAN-FIX-P5-S6.5c-A3-V6 (2026-04-22)
   ============================================================================
   V6 — Tighter Mid-Column Compression (MD Max + XL Min)

   Source: test-layout-triage-option-2a.html CSS_V6 (lines 513-557)
   Plan:   ~/.claude/plans/hi-we-are-compiled-meerkat.md Chunk 1.3
   Scope:  MD Max (820-1199 × ≤900h) + XL Min (1200-1424 × ≤900h).
           Triage composites inject V6 at both `final_md_max` (991×900) and
           `final_xl_min` (1200×800) alongside V4 + V12 (NOT V5). Width cap
           at 1424px prevents macOS scrollbar leak at exactly 1440 per
           ui-ninja review 2026-04-20; XL Baseline 1440×900 stays vanilla.
   Intent: Tighter compression than V5 (padding 18px 24px vs V5's 24px 30px;
           gap 6px vs 12px; 6px margins vs 12px) — targets the residual
           subtitle-container ↔ overview-trigger gap at MD Max 991×900 and
           title ↔ subtitle-container gap at XL Min 1200×800.
   Coexistence with Chunk 1.1 V4 at MD Max:
           V4 handles .project-subtitle-container flex layout (row flex +
           gap 24px + flex-start + child flex values). V6 handles spacing
           (padding, margin) on the SAME container. V4 sets `margin: 0`
           on .project-impact; V6 re-sets `margin: 0` — identical. V4's
           .project-subtitle-container gap (24px) overrides V6 because V4
           appears after V6 in source order? NO — V6 is appended AFTER V5
           which is AFTER V4 in file. Source-order-later wins at equal
           specificity. V6's `padding: 12px 18px` sets padding on the
           container (V4 doesn't touch padding) — no conflict. V6 does
           NOT set gap or flex-direction or align-items on
           .project-subtitle-container, so V4's layout values remain.

   Specificity: 0,2,0 on children + 0,1,0 on container root (matches
   baseline — overrides via !important).

   To revert: Search for CLEAN-FIX-P5-S6.5c-A3-V6 and delete everything
   between START and END markers.
   ============================================================================ */
@media (min-width: 820px) and (max-width: 1424px) and (max-height: 900px) {
    /* R4-V6-VERTICAL-COMPRESS 2026-04-28 — refines 6 V6 declared values
       + adds 1 new timeline-margin rule at this scope to fit project-info-column
       within column height budget at MD Max 991×900 (originally measured P2
       overflow: 88px). Total projected savings: 90px (12+12+12+12+6+36) — closes
       overflow with ~2px buffer. Affected scopes: MD Max (820-991 × ≤900h) +
       XL Min (1200-1424 × ≤900h). All target values 6n-compliant; design
       breathing room preserved (typography, asset sizes, content heights
       untouched — chrome only). ZERO new !important declarations.
       To revert ALL R4-V6-VERTICAL-COMPRESS modifications: `git revert <chunk-F-sha>`
       OR manually restore original values per inline annotations. Round-2
       fallback (per user direction 2026-04-28): if overcorrected, revert
       and ship a separate timeline-only Path A chunk.
       Inline `R4-V6-VERTICAL-COMPRESS` annotations mark each refined line. */
    .project-info-column {
        padding: 18px 24px !important;
        gap: 6px !important;
    }
    .project-info-column .project-title-expanded {
        margin-bottom: 0 !important;
    }
    .project-info-column .project-title-expanded h2 {
        line-height: 0.9 !important;
        margin: 0 !important;
    }
    .project-info-column .project-subtitle-container {
        padding: 6px 18px !important; /* R4-V6-VERTICAL-COMPRESS 2026-04-28: 12 → 6 vertical (preserve 18 horizontal); −12px */
        margin: 0 !important;
    }
    .project-info-column .project-subtitle {
        margin: 0 0 6px 0 !important;
        line-height: 1.3 !important;
    }
    .project-info-column .project-impact {
        margin: 0 !important;
        line-height: 1.35 !important;
    }
    .project-info-column .project-module {
        margin: 0 !important; /* R4-V6-VERTICAL-COMPRESS 2026-04-28: 6px 0 → 0; project-module is bottom-most child — column padding handles bottom-edge gap; −12px | V0-PRECURSOR-CONFIRMED 2026-05-05: spec-departure intentional per R4 column-budget recovery at MD Max 991×900; not revert-requested in subsequent sessions */
    }
    .project-info-column .work-categories {
        gap: 6px !important;
        margin: 0 !important; /* R4-V6-VERTICAL-COMPRESS 2026-04-28: 6px 0 → 0; column-gap (6px) handles spacing; −12px */
    }
    .project-info-column .overview-trigger {
        padding: 6px 18px !important; /* R4-V6-VERTICAL-COMPRESS 2026-04-28: 12 → 6 vertical (preserve 18 horizontal — Chunk E continues to override horizontal to 0); −12px | V0-PRECURSOR-CONFIRMED 2026-05-05: spec-departure intentional per R4 column-budget recovery; not revert-requested */
        margin-top: 0 !important; /* R4-V6-VERTICAL-COMPRESS 2026-04-28: 6 → 0; column-gap handles spacing above; −6px | V0-PRECURSOR-CONFIRMED 2026-05-05: spec-departure intentional per R4 column-budget recovery; not revert-requested */
    }
    /* R4-V6-VERTICAL-COMPRESS 2026-04-28: Timeline margin override — base rule
       at timeline-components-rebuilt.css:14 sets `margin: 30px 0` (60px chrome
       wrapping 60px content; 100% chrome ratio — biggest single offender).
       At V6 scope (MD Max + XL Min) tightening to 12/12 saves 36px. Specificity
       (0,2,0) wins over base (0,1,0); NO !important needed. Outside V6 scope
       (e.g., iPad Air 1194h, LG 992-1199, XL Baseline 1440+) timeline retains
       its base 30/30 rhythm where vertical budget allows. */
    .project-info-column .project-timeline-horizontal {
        margin: 12px 0;
    }
}
/* END CLEAN-FIX-P5-S6.5c-A3-V6 */


/* ============================================================================
   START CLEAN-FIX-P5-S6.5c-A3-V12-CSS (2026-04-22)
   ============================================================================
   V12 — Work-Categories Horizontal Marquee (MD Max + XL Min)

   Source: test-layout-triage-option-2a.html CSS_V12 (lines 583-645)
   Plan:   ~/.claude/plans/hi-we-are-compiled-meerkat.md Chunk 1.4a
   Scope:  820-1424 × ≤900h (MD Max + XL Min). Height-gate 900 matches
           V4/V6 spec boundary; width cap 1424 prevents macOS scrollbar
           leak at exactly 1440 (XL Baseline stays vanilla).
   Intent: Convert .work-categories from 2-row flex-wrap to single-row
           auto-scrolling horizontal marquee. Matches production's
           .hsec-fallback-marquee precedent (45s linear infinite).

   CONSUMES KEYFRAME `work-categories-marquee` from Chunk 1.4b
   (timeline-components-rebuilt.css). If that keyframe is missing,
   animation silently no-ops — marquee will render as static horizontal
   list without scroll.

   REQUIRES DOM WRAPPING FROM CHUNK 1.5 (V3CategoriesMarquee.js):
   The `.project-info-column .work-categories .work-categories-marquee-track`
   selector targets a wrapper that does NOT exist in baseline HTML.
   Chunk 1.5 JS creates the wrapper dynamically + duplicates category-tag
   children for seamless -50% loop. Without Chunk 1.5, this selector
   matches nothing and the marquee never forms.

   CONTAINER HEIGHT FIX (2026-04-20 via triage):
   .work-categories { display: block } collapses the container to 0h
   without explicit height. Explicit height: 42px + flex-shrink: 0
   restore the visual row; category-tag children get height: 24px +
   align-items: center for vertical centering.

   FADE COVERS (::before / ::after):
   12px solid var(--bg) blocks at left/right edges give brutalist
   hard-edge fade (not soft alpha mask — matches V3 aesthetic).

   Specificity: 0,2,0 + !important (port fidelity per plan).

   To revert: Search for CLEAN-FIX-P5-S6.5c-A3-V12-CSS and delete
   everything between START and END markers.
   ============================================================================ */
@media (min-width: 820px) and (max-width: 1424px) and (max-height: 900px) {
    .project-info-column .work-categories {
        display: block !important;
        overflow: hidden !important;
        position: relative !important;
        height: 42px !important;
        min-height: 42px !important;
        flex-shrink: 0 !important;
    }
    .project-info-column .work-categories::before,
    .project-info-column .work-categories::after {
        content: "" !important;
        position: absolute !important;
        top: 0 !important;
        bottom: 0 !important;
        width: 12px !important;
        background: var(--bg, #f5f5f0) !important;
        z-index: 2 !important;
        pointer-events: none !important;
    }
    .project-info-column .work-categories::before { left: 0 !important; }
    .project-info-column .work-categories::after  { right: 0 !important; }
    .project-info-column .work-categories .work-categories-marquee-track {
        display: flex !important;
        flex-wrap: nowrap !important;
        gap: 12px !important;
        width: max-content !important;
        height: 100% !important;
        align-items: center !important;
        animation: work-categories-marquee 45s linear infinite !important;
    }
    .project-info-column .work-categories .category-tag {
        display: inline-flex !important;
        align-items: center !important;
        flex-shrink: 0 !important;
        height: 24px !important;
        line-height: 1 !important;
        white-space: nowrap !important;
    }
}

/* Reduced-motion parity: suppress V12 marquee animation when user prefers
   reduced motion. Scoped inside the same width/height range as V12 itself
   so the reduced-motion rule only applies where V12 would otherwise fire. */
@media (prefers-reduced-motion: reduce) and (min-width: 820px) and (max-width: 1424px) and (max-height: 900px) {
    .project-info-column .work-categories .work-categories-marquee-track {
        animation: none !important;
    }
}
/* END CLEAN-FIX-P5-S6.5c-A3-V12-CSS */


/* ============================================================================
   START CLEAN-FIX-P5-S6.5c-A3-LG-SHELL (2026-04-23)
   ============================================================================
   LG shell + tier compression (Chunk 1.6a of 5 LG_MACRO sub-chunks)

   Source: test-layout-triage-option-2a.html CSS_LG_MACRO (lines 783-1005),
           specifically the universal vertical compression block at lines
           972-975: .project-info-column { padding: 12px 24px; gap: 12px }
   Plan:   ~/.claude/plans/hi-we-are-compiled-meerkat.md Chunks 1.6a-e
   Scope:  985-1199 × ≤700h (LG Min 992×600 + LG Short 992×700)

   BOUNDARY NOTE (triage line 785-790):
   min-width is 985, NOT 992. Triage deliberately loosened from 992→985 to
   accommodate iframe scrollbar overhead (test-responsive-production.html
   wrapper reduces LG Min 992 → inner width 989). Port-fidelity: keep 985.
   Still excludes iPad Air (inner ~831 < 985), MD Max (height 896 > 700),
   XL Min (height 796 > 700), and XL Baseline (width 1440 > 1199).
   Width range 985-991 overlaps standard MD tier (max 991) — accepted as
   triage-intended design; !important + source order later in cascade win.

   Intent: Minimum viable LG scope opener. Reclaims ~84px vertical across
   the 5 outer-column gaps for the LG Min 596h budget (was padding 42px
   18px + gap default; now 12px 24px + gap 12px = 84px savings).
   Applied UNIVERSALLY (not gated to P2-P6) so Macro E P1 (Chunk 1.6c)
   also benefits from compression.

   Specificity: 0,1,0 + !important (matches production baseline .project-info-column
   at project-column-styles.css:911; !important wins over non-important baseline).

   Dependencies: none. Independent first sub-chunk of LG_MACRO group.
   Subsequent chunks (1.6b Macro H, 1.6c Macro E P1, 1.6d LG marquee,
   1.6e LG timeline) will each add their own @media block at this same
   scope for revertability granularity.

   To revert: Search for CLEAN-FIX-P5-S6.5c-A3-LG-SHELL and delete
   everything between START and END markers.
   ============================================================================ */
@media (min-width: 820px) and (max-width: 1424px) and (max-height: 800px) { /* V0-PRECURSOR-FU-MD-LARGER-EXTEND 2026-05-05: was 985 — extended to cover MD-larger × ≤700h compressed-height composite (e.g., 920×600 broken-state fix). MIDPOINT-LG-SHELL-H-EXT 2026-05-06: was (max-width: 1199, max-height: 700) — extended width to 1424 (mirroring V6's reach) + height to 800 to cover 1024×768 (LG ≤800h) + 1200×600 + 1280×700 (XL ≤700h) per PIC harness empirical confirmation */
    .project-info-column {
        padding: 12px 24px !important;
        gap: 12px !important;
    }
}
/* END CLEAN-FIX-P5-S6.5c-A3-LG-SHELL */


/* ============================================================================
   START CLEAN-FIX-P5-S6.5c-A3-LG-MACRO-H (2026-04-23)
   ============================================================================
   Macro H — project-header grid + subtitle/impact hierarchy (Chunk 1.6b of 5)

   Source: test-layout-triage-option-2a.html CSS_LG_MACRO:
     - Lines 799-835 (project-header grid E1: coords + title)
     - Lines 837-867 (E2 subtitle/impact Classical Setup-Payoff)
     - Lines 869-872 (overview-trigger flex-shrink lock)
     - Lines 976-979 (subtitle-container universal compression override)
   Plan:   ~/.claude/plans/hi-we-are-compiled-meerkat.md Chunk 1.6b
   Scope:  985-1199 × ≤700h (same as 1.6a LG shell — separate @media block
           retained for independent revertability per Rollback Group D).

   Intent: Macro H is the hierarchy treatment common to P2-P6 at LG:
     - Project-header as 2-column CSS grid (60px coords + flexible title wrapper)
     - Coords-system positioned explicitly at 60×60 with project-number absolute
     - Title h2 compressed to 30px / line-height 1.05 (was ~44px causing 2-3 line wrap)
     - Subtitle-container with Classical Setup-Payoff: subtitle top (w600),
       impact bottom (w800) with 6px warm border-left
     - Overview-trigger flex-shrink: 0 to prevent squeeze at 596h budget
     - Final subtitle-container padding/gap override (6px → 12px) applies
       universally — triage's intentional source-order cascade within CSS_LG_MACRO.

   Project-header grid is UNIVERSAL at LG (applies to all 6 projects). The
   "Macro H" label refers to the P2-P6 hierarchy choices (subtitle+impact
   styling) that co-exist with this universal header grid. P1 gets order
   overrides in separate Chunk 1.6c (Macro E).

   Per-project accent: .project-impact border-left uses var(--warm) directly
   (not var(--accent-rgb)) — LG's impact always uses warm as its border color
   per triage line 859. For per-project accent color on IMPACT's border-left,
   production's baseline #projectN selectors (project-column-styles.css:539-574)
   set border-left-color via var(--warm/blue/pink/purple/darkblue/cyan). LG's
   `border-left: 6px solid var(--warm)` shorthand here locks the color to warm
   at LG scope, OVERRIDING per-project accents. This is triage-intentional —
   LG uses unified warm accent for Macro H visual coherence.

   Specificity: 0,2,0 / 0,3,0 / 0,4,0 + !important (port fidelity).
   Production baseline at 0,1,0 / 0,2,0 etc. LG rules win.

   Dependencies: none hard. 1.6a LG shell already committed for .project-info-column
   tier-1 padding/gap. This chunk (1.6b) does not depend on 1.6a for correctness
   but both firing together produces the intended composite.

   To revert: Search for CLEAN-FIX-P5-S6.5c-A3-LG-MACRO-H and delete everything
   between START and END markers.
   ============================================================================ */
@media (min-width: 820px) and (max-width: 1424px) and (max-height: 800px) { /* V0-PRECURSOR-FU-MD-LARGER-EXTEND 2026-05-05: was 985 — extended to cover MD-larger × ≤700h compressed-height composite (e.g., 920×600 broken-state fix). MIDPOINT-MC-2..5-EXT 2026-05-06: was (max-width: 1199, max-height: 700) — bundled extension paired with MC-1 LG Shell (commit 808c79e) per Phase A cascade-fix; widened width to 1424 (mirroring V6's reach) + height to 800 to cover 1024×768 + 1200×600 + 1280×700 broken composites */
    /* E1 — project-header grid (universal at LG, applies to all 6 projects) */
    .project-info-column .project-header {
        display: grid !important;
        grid-template-columns: 60px 1fr !important;
        gap: 12px !important;
        align-items: start !important;
        position: relative !important;
    }
    .project-info-column .project-header .coords-system {
        width: 60px !important;
        height: 60px !important;
        position: relative !important;
        margin: 0 !important;
    }
    .project-info-column .project-header .coords-system .project-number {
        font-size: 30px !important;
        line-height: 1 !important;
        font-weight: 900 !important;
        top: 6px !important;
        left: 6px !important;
        opacity: 1 !important;
        position: absolute !important;
        /* R4-LG-MACRO-H-PER-PROJECT-ACCENT 2026-04-28: removed `color: #303333 !important;` — let
           base #projectN .accent-color (project-column-styles.css:2502+) cascade for per-project
           accent on the EXPANDED-state project-number (the "4D°" / "H+M" / "S*F" symbols nested
           inside .coords-system). Restores blue/pink/purple/darkblue/cyan at LG-short scope.
           Net !important delta for this edit: -1 (paired with impact longhand split below: net 0). */
    }
    .project-info-column .project-header .project-title-expanded {
        margin: 0 !important;
    }
    /* Title h2 compression: 44px wraps 2-3 lines in 386px title col → header ~140px tall.
       30px fits on 1-2 lines, saves ~30-60px header height at LG. */
    .project-info-column .project-header .project-title-expanded h2 {
        font-size: 30px !important;
        font-weight: 800 !important;
        line-height: 1.05 !important;
        text-transform: uppercase !important;
        margin: 0 !important;
    }

    /* E2 — 2A Classical Setup-Payoff (subtitle w600 top, impact w800 bottom with 6px warm border-left) */
    .project-info-column .project-subtitle-container {
        display: flex !important;
        flex-direction: column !important;
        gap: 6px !important;
        padding: 6px !important;
        background: transparent !important;
        box-shadow: none !important;
    }
    .project-info-column .project-subtitle {
        font-size: 11px !important;
        font-weight: 600 !important;
        line-height: 1.25 !important;
        color: #303333 !important;
        margin: 0 !important;
        order: 1 !important;
    }
    .project-info-column .project-impact {
        font-size: 13px !important;
        font-weight: 800 !important;
        line-height: 1.25 !important;
        /* R4-LG-MACRO-H-PER-PROJECT-ACCENT 2026-04-28: split `border-left: 6px solid var(--warm) !important;`
           into longhand style+width only. border-left-color now cascades from base
           #projectN .project-impact rules (project-column-styles.css:539-575) for per-project
           border accent (warm/blue/pink/purple/darkblue/cyan). 1 shorthand !important removed,
           2 longhand !important added; net edit delta: +1 (paired with project-number color
           removal above: chunk net delta: 0). */
        border-left-style: solid !important;
        border-left-width: 6px !important;
        padding-left: 12px !important;
        margin: 0 !important;
        order: 2 !important;
    }
    .project-info-column .highlight {
        font-weight: 900 !important;
        color: #121212 !important;
    }

    /* Overview-trigger flex-shrink lock (prevents squeeze at LG Min 596 budget) */
    .project-info-column .overview-trigger {
        flex-shrink: 0 !important;
    }

    /* Subtitle-container universal compression override — triage's intentional
       source-order cascade. The earlier rule sets padding:6px + gap:6px; this
       later rule overrides to padding:12px + gap:12px for hierarchy polish.
       Port-fidelity retains both rules. */
    .project-info-column .project-subtitle-container {
        padding: 12px !important;
        gap: 12px !important;
    }
}
/* END CLEAN-FIX-P5-S6.5c-A3-LG-MACRO-H */


/* ============================================================================
   START CLEAN-FIX-P5-S6.5c-A3-LG-MACRO-E-P1 (2026-04-23)
   ============================================================================
   Macro E — P1 custom order + CTA full-width (Chunk 1.6c of 5)

   Source: test-layout-triage-option-2a.html CSS_LG_MACRO lines 929-960
   Plan:   ~/.claude/plans/hi-we-are-compiled-meerkat.md Chunk 1.6c
   Scope:  985-1199 × ≤700h (same LG scope as 1.6a/1.6b — separate @media
           block for independent revertability).
   Target: P1 only via `.project-column[data-index="1"]` selector chain.

   Intent: P1 at LG differs from P2-P6 because P1 lacks a
   .project-timeline-horizontal (its structure is case-study overview
   with .case-study-cta instead of timeline). Macro E provides:
     - Custom child order (work-categories promoted 4→3 to fill the visual
       beat-gap where timeline would otherwise be; CTA + module pushed to
       bottom positions 5-6)
     - Full-width bordered CTA button treatment (case-study-cta becomes
       primary action at bottom of P1 column)
     - 24×24 cta-module icon with 1px border

   Why P1-only: P2-P5 have their cycling timeline at LG via Chunk 1.6e.
   P6 uses P6 guide marquee (F.sec_guide_strings handled elsewhere).
   Only P1 needs this reorder + CTA styling at LG.

   Specificity: 0,2,1 on `.project-column[data-index="1"] .project-info-column`
   selector chain (attribute selector adds 1). Higher than 1.6b's 0,2,0 +
   !important, so P1 order rules win cleanly.

   Dependencies: 1.6b must have landed (project-header grid shared); 1.6a
   tier-1 compression recommended for correct CTA bottom alignment.

   To revert: Search for CLEAN-FIX-P5-S6.5c-A3-LG-MACRO-E-P1 and delete
   everything between START and END markers.
   ============================================================================ */
@media (min-width: 820px) and (max-width: 1424px) and (max-height: 800px) { /* V0-PRECURSOR-FU-MD-LARGER-EXTEND 2026-05-05: was 985 — extended to cover MD-larger × ≤700h compressed-height composite (e.g., 920×600 broken-state fix). MIDPOINT-MC-2..5-EXT 2026-05-06: was (max-width: 1199, max-height: 700) — bundled extension paired with MC-1 LG Shell (commit 808c79e) per Phase A cascade-fix; widened width to 1424 (mirroring V6's reach) + height to 800 to cover 1024×768 + 1200×600 + 1280×700 broken composites */
    /* Macro E P1 custom order — work-cats promoted 4→3 to fill timeline beat-gap */
    .project-column[data-index="1"] .project-info-column > .project-header             { order: 1 !important; }
    .project-column[data-index="1"] .project-info-column > .project-subtitle-container { order: 2 !important; }
    .project-column[data-index="1"] .project-info-column > .work-categories            { order: 3 !important; }
    .project-column[data-index="1"] .project-info-column > .overview-trigger           { order: 4 !important; }
    .project-column[data-index="1"] .project-info-column > .case-study-cta             { order: 5 !important; }
    .project-column[data-index="1"] .project-info-column > .project-module             { order: 6 !important; }

    /* Macro E P1 CTA — VI-B1 3C Decoration Strip Minimal port (2026-05-07).
       Inline annotation — modify-in-place inside existing fence per CLAUDE.md
       modify-in-place precedent. Source: test-lg-element-variations.html
       lines 522-569 ('3C — Decoration Strip Minimal — cube rotation REVIVED').
       3C aesthetic: STRIP background + STRIP border on chrome elements; preserve
       cube perspective for 3D rotation; resize indicator/pulse/module/cube to
       3C dimensions. Per-project accent preserved via existing line 1135 rule.
       ZERO new !important (uses existing fence !important infrastructure). */
    .project-column[data-index="1"] .project-info-column .case-study-cta {
        width: 100% !important;
    }
    .project-column[data-index="1"] .project-info-column .case-study-cta .view-case-btn {
        padding: 6px 0 !important;
        background-color: transparent !important;     /* VI-B1: was #e8e6e1 (strip bg) */
        border: none !important;
        width: 100% !important;
        height: 42px !important;                      /* VI-B1: was 36px (3C: 42px) */
        color: #303333 !important;
        display: flex !important;
        align-items: center !important;
        gap: 12px !important;
        justify-content: flex-start !important;
    }
    .project-column[data-index="1"] .project-info-column .case-study-cta .view-case-btn .cta-module {
        width: 24px !important;
        height: 24px !important;
        border: none !important;                      /* VI-B1: was 1px solid #303333 (strip border) */
        background-color: transparent !important;    /* VI-B1: was #e8e6e1 (strip bg) */
        display: block !important;
        position: relative !important;
        flex-shrink: 0 !important;
    }
    /* VI-B1: 3C indicator — 8×8 dot (was 4×4). Per-project accent inherited from
       project-column-styles.css:1135 (#project1 → var(--warm)). */
    .project-column[data-index="1"] .project-info-column .case-study-cta .view-case-btn .module-indicator {
        width: 8px !important;
        height: 8px !important;
        position: absolute !important;
        top: 8px !important;
        left: 8px !important;
        margin: 0 !important;
        opacity: 1 !important;
    }
    /* VI-B1: 3C pulse-ring — 16×16 centered on indicator (translate-centering since
       production DOM nests pulse-ring inside module-indicator at 8×8 parent).
       Production keyframe at CLEAN-FIX-P5-S7C2B-M2-SET3-PULSE (line 1169) preserved. */
    .project-column[data-index="1"] .project-info-column .case-study-cta .view-case-btn .module-indicator .pulse-ring {
        width: 16px !important;
        height: 16px !important;
        top: 50% !important;
        left: 50% !important;
        transform: translate(-50%, -50%) !important;
        border: 1px solid var(--warm) !important;     /* VI-B1: per-project accent (P1 warm) */
        background-color: transparent !important;
        opacity: 0.5 !important;
    }
    /* VI-B1: 3C cube-wrapper — 140×24 with perspective preserved for 3D rotation.
       Production .cube, .cube-face.front, .cube-face.back rules handle the rotate animation;
       hover trigger at project-column-styles.css:1249. */
    .project-column[data-index="1"] .project-info-column .case-study-cta .view-case-btn .cube-wrapper {
        width: 140px !important;
        height: 24px !important;
        perspective: 600px !important;
        transform-style: flat !important;
        overflow: hidden !important;
        position: relative !important;
        background: transparent !important;            /* VI-B1: strip bg */
        margin-left: 12px !important;
        flex-grow: 0 !important;
        display: block !important;
    }

    /* === VI-B2-M4B-BRACKETS-M4D-HOVER (modify-in-place 2026-05-11) ===========
       Mirror of project-column-styles.css:3893-3952 VI-B2 additions for the LG-MACRO
       compressed-mode composite (820-1424 × ≤800h). !important required per L8
       cascade-add discipline at this scope (fence's existing !important pattern).
       Identical visual outcome to the non-!important rules in the 3C fence — fence-
       parity invariant preserved.
       To revert: delete from `/* === VI-B2-M4B-BRACKETS-M4D-HOVER` through this
       rule's closing `}`. ZERO impact on LG-MACRO-E-P1 base. */
    .project-column[data-index="1"] .project-info-column .case-study-cta .view-case-btn {
        transition: box-shadow 200ms ease-out !important;
    }
    .project-column[data-index="1"] .project-info-column .case-study-cta .view-case-btn::before {
        content: '' !important;
        position: absolute !important;
        top: 0 !important;
        left: 0 !important;
        width: 12px !important;
        height: 12px !important;
        border-top: 2px solid rgb(var(--warm-rgb)) !important;
        border-left: 2px solid rgb(var(--warm-rgb)) !important;
        pointer-events: none !important;
        animation: p1-cta-m4b-bracket-pulse 2.5s ease-in-out infinite !important;
    }
    .project-column[data-index="1"] .project-info-column .case-study-cta .view-case-btn::after {
        content: '' !important;
        position: absolute !important;
        bottom: 0 !important;
        right: 0 !important;
        width: 12px !important;
        height: 12px !important;
        border-bottom: 2px solid rgb(var(--warm-rgb)) !important;
        border-right: 2px solid rgb(var(--warm-rgb)) !important;
        pointer-events: none !important;
        animation: p1-cta-m4b-bracket-pulse 2.5s ease-in-out infinite !important;
    }
    .project-column[data-index="1"] .project-info-column .case-study-cta .view-case-btn:hover {
        box-shadow: inset 0 1px 0 0 rgb(var(--warm-rgb)), inset 0 -2px 0 0 rgb(var(--warm-rgb)) !important;
    }
}
/* END CLEAN-FIX-P5-S6.5c-A3-LG-MACRO-E-P1 */


/* ============================================================================
   START CLEAN-FIX-P5-SESSION8-F1-REDUCED-MOTION-LG-MACRO (2026-05-13)
   ============================================================================
   Patches F1 reduced-motion regression at compressed-mode 820-1424 × ≤800h.

   Why: the LG-MACRO-E-P1 VI-B2 mirror above (L4100-4138) declares
   `animation: p1-cta-m4b-bracket-pulse ... !important` (L4121/L4133) and
   `transition: box-shadow ... !important` (L4109) at the compressed-mode
   composite. The reduced-motion silencer in `project-column-styles.css:4008-4016`
   loses source-order cascade vs responsive.css at this composite (same
   specificity, same !important, source order wins per index.html:39/43 load
   order). Users with `prefers-reduced-motion: reduce` still see bracket pulse
   + hover transition at LG ≤800h before this patch.

   Fix: additive @media block nesting reduced-motion gate inside LG-MACRO scope.
   +2 active !important (accessibility exception per existing fence discipline).

   Surfaced by code-review-analyst Session-8 3-agent plan review 2026-05-13 as
   HIGH-severity F1 finding on Session-7 commit 41eaddc dual-fence VI-B2 port.

   To revert: search for CLEAN-FIX-P5-SESSION8-F1-REDUCED-MOTION-LG-MACRO and
   delete everything between START and END markers. ZERO impact on other
   composites. ============================================================ */

@media (prefers-reduced-motion: reduce) {
    @media (min-width: 820px) and (max-width: 1424px) and (max-height: 800px) {
        .project-column[data-index="1"] .project-info-column .case-study-cta .view-case-btn::before,
        .project-column[data-index="1"] .project-info-column .case-study-cta .view-case-btn::after {
            animation: none !important;
        }
        .project-column[data-index="1"] .project-info-column .case-study-cta .view-case-btn {
            transition: none !important;
        }
    }
}

/* END CLEAN-FIX-P5-SESSION8-F1-REDUCED-MOTION-LG-MACRO */


/* ============================================================================
   START CLEAN-FIX-P5-S6.5c-A3-LG-MARQUEE (2026-04-23)
   ============================================================================
   LG work-categories horizontal marquee — 30px variant (Chunk 1.6d of 5)

   Source: test-layout-triage-option-2a.html CSS_LG_MACRO lines 874-924
           + reduced-motion parity block
   Plan:   ~/.claude/plans/hi-we-are-compiled-meerkat.md Chunk 1.6d
   Scope:  985-1199 × ≤700h (LG-specific marquee variant; OVERRIDES V12's
           42px marquee at LG viewports via source order — this block
           is appended after V12 CSS so wins at equal specificity).
   Consumes: `viewer-marquee` @keyframes from timeline-components-rebuilt.css
             (Chunk 1.4b; 30s translateX 0 → -50% — tighter cadence than
             V12's work-categories-marquee 45s for LG's denser layout).
   Consumes: V3CategoriesMarquee DOM wrapping from Chunk 1.5 (singleton
             matchMedia 820-1424 × ≤900h already active at LG viewports
             since LG band is nested inside V12 matchMedia query).

   Intent: LG variant of V12 marquee with:
     - Container height 30px (vs V12's 42px) for tighter LG 596-696h budget
     - Smaller tag typography (10.4px vs V12's inherited default)
     - Per-project accent border-left on .category-tag using --accent-rgb
       (cascades from #projectN rules at project-column-styles.css:2346+
       hoisted to :root per 7B.0b commit). Warm fallback if var unset.
     - Uppercase letter-spaced tag labels (triage's brutalist detail work)
     - viewer-marquee 30s cadence (faster than V12's 45s for more active feel)

   Reduced-motion parity: separate @media (prefers-reduced-motion: reduce)
   block at same scope suppresses animation for motion-sensitive users.

   CASCADE OVERRIDE OVER V12 (critical):
   V12 @media fires at 820-1424 × ≤900h — includes LG viewports. V12 sets
   .work-categories height: 42px + animation: work-categories-marquee 45s.
   This Chunk 1.6d @media fires at 985-1199 × ≤700h — OVERLAPPING with V12.
   Both @media blocks are 0,2,0 + !important specificity. Source order:
   V12 at commit 3674d3b (earlier), LG_MARQUEE this commit (later) → LG
   wins at LG viewports. At MD Max / XL Min, LG doesn't fire (height > 700),
   V12 alone applies with 42px + 45s.

   Fade cover background: triage hardcodes `#f5f5f0` (NOT var(--bg))
   — port-fidelity retains hardcoded hex.

   Specificity: 0,2,0 (selectors) + 0,3,0 (>*) + !important.

   To revert: Search for CLEAN-FIX-P5-S6.5c-A3-LG-MARQUEE and delete
   everything between START and END markers.
   ============================================================================ */
@media (min-width: 820px) and (max-width: 1424px) and (max-height: 800px) { /* V0-PRECURSOR-FU-MD-LARGER-EXTEND 2026-05-05: was 985 — extended to cover MD-larger × ≤700h compressed-height composite (e.g., 920×600 broken-state fix). MIDPOINT-MC-2..5-EXT 2026-05-06: was (max-width: 1199, max-height: 700) — bundled extension paired with MC-1 LG Shell (commit 808c79e) per Phase A cascade-fix; widened width to 1424 (mirroring V6's reach) + height to 800 to cover 1024×768 + 1200×600 + 1280×700 broken composites */
    .project-info-column .work-categories {
        display: block !important;
        overflow: hidden !important;
        position: relative !important;
        height: 30px !important;
        min-height: 30px !important;
        flex-shrink: 0 !important;
        background: transparent !important;
    }
    .project-info-column .work-categories::before,
    .project-info-column .work-categories::after {
        content: "" !important;
        position: absolute !important;
        top: 0 !important;
        bottom: 0 !important;
        width: 12px !important;
        background: #f5f5f0 !important;
        z-index: 2 !important;
        pointer-events: none !important;
    }
    .project-info-column .work-categories::before { left: 0 !important; }
    .project-info-column .work-categories::after  { right: 0 !important; }
    /* Category-tag per-project accent: var(--accent-rgb) cascades from #projectN
       rule at project-column-styles.css:2346+ (hoisted to :root per 7B.0b).
       Fallback `121, 126, 128` is the --warm RGB for pre-hoist state. */
    .project-info-column .work-categories .category-tag {
        display: inline-flex !important;
        align-items: center !important;
        flex-shrink: 0 !important;
        font-size: 10.4px !important;
        /* Port-fidelity triage value (non-6n by design). User-authorized
           hook override for Phase 1 triage-confirmed decisions 2026-04-23.
           Visual intent: tighter vertical, slight horizontal breathing
           vs the 6n-default would provide. Flagged for Phase 10.19. */
        padding: 4px 10px !important;
        background: #e8e6e1 !important;
        border-left: 2px solid rgb(var(--accent-rgb, 121, 126, 128)) !important;
        margin-right: 12px !important;
        text-transform: uppercase !important;
        letter-spacing: 0.04em !important;
        font-weight: 500 !important;
        white-space: nowrap !important;
        height: 24px !important;
        line-height: 1 !important;
        vertical-align: middle !important;
        color: #303333 !important;
    }
    /* Direct children animation via viewer-marquee (30s cadence, LG variant).
       Targets .work-categories-marquee-track wrapper created by
       V3CategoriesMarquee.js (Chunk 1.5) — same DOM as V12 consumes, but
       animation keyframe + duration differ at LG scope. */
    .project-info-column .work-categories > * {
        animation: viewer-marquee 30s linear infinite !important;
        white-space: nowrap !important;
        display: inline-block !important;
    }
}

/* Reduced-motion parity: suppress LG marquee animation for motion-sensitive users.
   Scoped to same LG band (985-1199 × ≤700h) so it only applies where LG
   marquee would otherwise fire. Mirrors the V12 reduced-motion block pattern. */
@media (prefers-reduced-motion: reduce) and (min-width: 820px) and (max-width: 1424px) and (max-height: 800px) { /* V0-PRECURSOR-FU-MD-LARGER-EXTEND 2026-05-05: was 985 — paired with primary @media block extension for reduced-motion parity. MIDPOINT-MC-2..5-EXT 2026-05-06: was (max-width: 1199, max-height: 700) — paired with primary block widening (commit 808c79e + MC-2..5 bundle) for reduced-motion accessibility parity at extended scope */
    .project-info-column .work-categories > * {
        animation: none !important;
    }
}
/* END CLEAN-FIX-P5-S6.5c-A3-LG-MARQUEE */


/* ============================================================================
   START CLEAN-FIX-P5-S6.5c-R4-CYCLING-TIMELINE-MD-PORT (2026-04-27)
   ============================================================================
   MD Max (820-991) cycling timeline — port from triage source-of-truth.

   Source: test-layout-triage-option-2a.html:300-308 (H3-ALT REV v2)

   Why this chunk: A3.6e (commit cdb7cbe) ported the LG-short cycling scope
   (985-1199 × ≤700h) but did NOT port the triage 820-991 (MD Max) scope
   which is the original H3-ALT REV intent. iPad Air 834×1194 falls outside
   LG-short (1194 > 700h gate) so no cycling fires there. This chunk closes
   that gap; surfaced via Phase II Preset 1 testing 2026-04-27.

   Scope: 820-991 (MD Max). Composes additively with the existing LG-short
   block immediately below (4121-4199) — kept per dual-scope decision
   2026-04-27 for LG short-height variants where cycling is also wanted.

   !important discipline: this chunk uses NO !important per CLAUDE.md
   "no new !important" rule — specificity (0,4,0) on the descendant chain
   wins on its own (no upstream rules conflict at 820-991 scope; verified
   via grep of .platform-stage .stage-label rules in production CSS).
   Diverges intentionally from A3.6e LG-short block (4121-4199) which has
   !important on transition / animation / animation-fill-mode / animation-delay
   — that block was authored before the strict no-new-!important rule was
   applied to new chunks. Both blocks apply identical animation values,
   so no functional divergence at the 985-991 × ≤700h overlap (LG-short
   still wins via !important; same end state). Phase 10.19 audit-tracked.

   Reduced-motion paired block: source-order-after the cycling block at
   the same scope; same specificity. Source order resolves the cascade —
   no !important needed in either block.

   Dependencies: keyframe `triage-label-cycle-reveal` already exists at
   timeline-components-rebuilt.css:557-563 (ported in A3.4b commit c3662d7).

   To revert: search for CLEAN-FIX-P5-S6.5c-R4-CYCLING-TIMELINE-MD-PORT
   and delete everything between START and END markers.
   ============================================================================ */
@media (min-width: 820px) and (max-width: 991px) {
    .project-info-column .project-timeline-horizontal .platform-stage .stage-label {
        opacity: 0;
        transition: opacity 200ms ease;
        animation: triage-label-cycle-reveal 12s ease-in-out infinite;
        animation-fill-mode: both;
    }
    .project-info-column .project-timeline-horizontal .timeline-track > .platform-stage:nth-child(1) .stage-label { animation-delay: 0s; }
    .project-info-column .project-timeline-horizontal .timeline-track > .platform-stage:nth-child(2) .stage-label { animation-delay: 4s; }
    .project-info-column .project-timeline-horizontal .timeline-track > .platform-stage:nth-child(3) .stage-label { animation-delay: 8s; }
}

@media (prefers-reduced-motion: reduce) and (min-width: 820px) and (max-width: 991px) {
    .project-info-column .project-timeline-horizontal .platform-stage .stage-label {
        opacity: 1;
        animation: none;
        transition: none;
    }
}
/* END CLEAN-FIX-P5-S6.5c-R4-CYCLING-TIMELINE-MD-PORT */


/* ============================================================================
   START CLEAN-FIX-P5-S6.5c-A3-LG-TIMELINE-CYCLE (2026-04-23)
   ============================================================================
   LG cycling timeline — P2-P5 only (Chunk 1.6e of 5, final LG_MACRO chunk)

   Source: test-layout-triage-option-2a.html CSS_LG_MACRO lines 987-1004
           + reduced-motion parity block at lines 1014+
   Plan:   ~/.claude/plans/hi-we-are-compiled-meerkat.md Chunk 1.6e
   Scope:  985-1199 × ≤700h (LG Min/Short). P1 and P6 do not have
           .project-timeline-horizontal so these rules are a no-op for
           those projects. P2, P3, P4, P5 get the cycling label reveal.

   Consumes: `triage-label-cycle-reveal` @keyframes from
             timeline-components-rebuilt.css (Chunk 1.4b). 12s duration,
             opacity keyframes 0%→0, 2%→1, 31%→1, 33%→0, 100%→0 (29%
             visible window). Paired with nth-child animation-delay:
             0s/4s/8s across 3 platform-stage children — labels cycle
             sequentially with ~0.52s gaps between.

   Intent: At LG height budget 596-696h, a full static 3-label timeline
           (CONFRONTATION + CALIBRATION + TRANSCENDENCE for P2) takes
           vertical space. Cycling reveals one label at a time in a
           compressed 30px-tall timeline strip, freeing vertical budget
           for other children while still communicating project phasing.

   CRITICAL OPACITY SEMANTICS (triage line 992-995 comment):
   The .stage-label opacity: 0 is INTENTIONALLY without !important.
   Per CSS spec, an !important declaration on a property BEATS animation
   keyframes. If opacity: 0 !important were set, the keyframe's opacity:
   1 values (at 2%-31% of cycle) would never apply — labels would stay
   invisible. Using opacity: 0 without !important still wins over
   .project-column.active * { opacity: 1 } via higher specificity, while
   allowing the keyframe's opacity: 1 frames to fire. animation-fill-mode:
   both ensures the 0% keyframe (opacity 0) applies backwards through
   the animation-delay period for each nth-child.

   Specificity: 0,3,0 on .project-info-column .project-timeline-horizontal
   .platform-stage .stage-label + !important on non-opacity properties.

   Dependencies: 1.4b keyframes (triage-label-cycle-reveal) must exist.

   To revert: Search for CLEAN-FIX-P5-S6.5c-A3-LG-TIMELINE-CYCLE and
   delete everything between START and END markers.

   V0-PRECURSOR-D4-CONFIRMED (2026-05-05): V0 4-tier × 6-project audit
   verified production cycling values (12s duration + 0/4/8s stagger) are
   the post-ui-ninja-2026-04-20-review canonical for LG. lg-only triage
   (rebuilt 2026-04-18) holds the PRE-review draft (9s × 0/3/6s × 23%
   peak); the ui-ninja review widened to 12s × 29% peak for LG. Production
   correctly tracks the post-review state. Paired keyframe annotation at
   timeline-components-rebuilt.css:552-565.
   ============================================================================ */
@media (min-width: 820px) and (max-width: 1424px) and (max-height: 800px) { /* V0-PRECURSOR-FU-MD-LARGER-EXTEND 2026-05-05: was 985 — extended to cover MD-larger × ≤700h compressed-height composite (e.g., 920×600 broken-state fix). MIDPOINT-MC-2..5-EXT 2026-05-06: was (max-width: 1199, max-height: 700) — bundled extension paired with MC-1 LG Shell (commit 808c79e) per Phase A cascade-fix; widened width to 1424 (mirroring V6's reach) + height to 800 to cover 1024×768 + 1200×600 + 1280×700 broken composites */
    /* Timeline strip compression: base ~72px → 30px at LG (reclaim 42px
       for overview-trigger, module, etc. to fit in 596h budget). */
    .project-info-column .project-timeline-horizontal {
        height: 30px !important;
        flex-shrink: 0 !important;
        padding: 0 12px !important;
    }
    /* Stage-label opacity cycling — opacity:0 intentionally WITHOUT !important
       (per triage comment) so keyframe opacity:1 frames can fire via
       animation-fill-mode: both. See full rationale in block header. */
    .project-info-column .project-timeline-horizontal .platform-stage .stage-label {
        opacity: 0;
        transition: opacity 200ms ease !important;
        animation: triage-label-cycle-reveal 12s ease-in-out infinite !important;
        animation-fill-mode: both !important;
    }
    /* Staggered delays across 3 platform-stages: 0s/4s/8s in 12s cycle.
       Combined with 29% visible window = each label visible for 3.48s
       with ~0.52s gap before next. Seamless sequential reveal.
       (V0-PRECURSOR-D4-CONFIRMED 2026-05-05 — post-ui-ninja-review canonical.) */
    .project-info-column .project-timeline-horizontal .timeline-track > .platform-stage:nth-child(1) .stage-label { animation-delay: 0s !important; }
    .project-info-column .project-timeline-horizontal .timeline-track > .platform-stage:nth-child(2) .stage-label { animation-delay: 4s !important; }
    .project-info-column .project-timeline-horizontal .timeline-track > .platform-stage:nth-child(3) .stage-label { animation-delay: 8s !important; }
}

/* Reduced-motion parity for LG cycling timeline: show all labels statically
   (opacity 1) with no animation for motion-sensitive users. Scoped to LG
   band to only affect where the cycling would otherwise fire. */
@media (prefers-reduced-motion: reduce) and (min-width: 820px) and (max-width: 1424px) and (max-height: 800px) { /* V0-PRECURSOR-FU-MD-LARGER-EXTEND 2026-05-05: was 985 — paired with primary @media block extension for reduced-motion parity. MIDPOINT-MC-2..5-EXT 2026-05-06: was (max-width: 1199, max-height: 700) — paired with primary block widening (commit 808c79e + MC-2..5 bundle) for reduced-motion accessibility parity at extended scope */
    .project-info-column .project-timeline-horizontal .platform-stage .stage-label {
        opacity: 1 !important;
        animation: none !important;
        transition: none !important;
    }
}
/* END CLEAN-FIX-P5-S6.5c-A3-LG-TIMELINE-CYCLE */


/* ============================================================================
   START CLEAN-FIX-P5-S6.5c-A3-TITLE-BREAK (2026-04-23)
   ============================================================================
   Title-break display toggle (Chunk 1.7, final Phase 1 chunk)

   Source: test-layout-triage-option-2a.html lines 156-173
           (CSS selector) + applyTitleBreaks() JS at line 1133
           (replaced by static HTML markup in production per plan).
   Plan:   ~/.claude/plans/hi-we-are-compiled-meerkat.md Chunk 1.7
   Scope:  Shown at 820-991 (MD Max range); hidden at <820 (XS/SM) and
           ≥992 (LG/XL). Triage-exact scope (plan table entry was a
           paraphrase — verified against triage source 2026-04-23).

   Intent: P2/P3/P4 titles (t.i.m.E, [AI]rBnB, SaveFace) are narrow-
           column-friendly at LG/XL where .project-info-column is wide
           enough to render them single-line, but at MD Max 991×900 the
           title column is only ~386px wide which forces awkward wraps.
           Inserting an explicit `<br class="title-break-820">` at the
           visual hinge point (t.i.|m.E, [AI]|rBnB, Save|Face) gives a
           controlled 2-line wrap in MD range. Hidden elsewhere via this
           CSS toggle so single-line rendering is preserved at LG+.

   IMPLEMENTATION NOTE (production vs triage):
   Triage uses JS `applyTitleBreaks()` to inject the `<br>` at runtime
   because triage injects CSS via iframe without editing index.html.
   Production gets STATIC HTML — the `<br class="title-break-820">` lives
   directly in index.html P2/P3/P4 h2 markup (wrapped in the same
   CLEAN-FIX-P5-S6.5c-A3-TITLE-BREAK marker block). No JS needed in
   production; cleaner performance + easier revert.

   Specificity: 0,1,0 on `.title-break-820`. No !important needed — the
   `<br>` element has no default `display: block` on modern browsers
   (actually defaults to `display: inline` in most browsers, though in
   practice renders as a line-break regardless). The explicit display
   toggle works on the CSS-computed value, forcing block at 820-991
   (visible line-break) and none elsewhere (no space at all).

   Dependencies:
   - Chunk 1.3 V6 scope exists at 820-1424 (which includes this chunk's
     820-991 range) — not a strict dependency but V6 fires at same width
     band so title-break composes cleanly with V6's compressed typography.
   - index.html P2 (line 488), P3 (line 923), P4 (line 1350) have the
     `<br>` markup inserted (same CLEAN-FIX marker name, _P2/_P3/_P4
     suffix in HTML comments for locate-by-project).

   To revert this chunk completely:
   1. Search `src/v3/styles/v3-project-columns-responsive.css` for
      CLEAN-FIX-P5-S6.5c-A3-TITLE-BREAK and delete this block.
   2. Search `index.html` for CLEAN-FIX-P5-S6.5c-A3-TITLE-BREAK and
      delete all 3 marker blocks (P2 line 488, P3 line 923, P4 line 1350).
      Each block collapses back to the original `<h2>...</h2>` without
      the `<br>`.
   ============================================================================ */
.title-break-820 {
    display: none;
}
/* V0-PRECURSOR-FU-TITLE-BREAK-RETIRE 2026-05-05: the @media block that previously
   set `.title-break-820 { display: block }` at 820-1199 (V-S11 extension, commit
   09107c9 2026-05-05) AND originally at 820-991 (Phase III A3 port baseline) is
   RETIRED here. With LG-MACRO compression now extended to MD-larger (820-1199 × ≤700h)
   via V0-PRECURSOR-FU-MD-LARGER-EXTEND, h2 compresses to 30px at all compressed-height
   composites — titles "[AI] rBnB" / "t.i. m.E" / "Save Face" fit on a single line
   without forced break. Default rule above (lines 4378-4380) keeps `.title-break-820
   { display: none }` at all widths; HTML BR elements at index.html:495 (P2) / 933 (P3) /
   1363 (P4) remain in markup for revertability but render no visible break.
   Per user direction 2026-05-05: "project-title-expanded needs to be version with NO
   line break as plenty of space (likely all screen iterations WIDER than ~768px)".
   To revert (re-enable break at narrow widths if needed):
       @media (min-width: 820px) and (max-width: 1199px) {
           .title-break-820 { display: block; }
       }
   OR scope to mobile only via @media (max-width: 768px) { ... } per future need. */
/* END CLEAN-FIX-P5-S6.5c-A3-TITLE-BREAK */


/* ============================================================================
   START CLEAN-FIX-P5-S6.5c-R4-MASONRY-COLCOUNT-TRIAGE-PORT (2026-04-27)
   ============================================================================
   MD Max (820-991) masonry 1-col stack — port from triage source-of-truth
   (FIX A v2 + FIX D v2 paired chunk).

   Sources:
     - test-layout-triage-option-2a.html:287-292 (FIX A v2 — .asset-container
       flex-basis override; supersedes FIX A v1 retired at triage:146-154
       for combinator-reach reasons: JS-injected .marquee-wrapper between
       .mockups-masonry and its children breaks the `>` direct-child path,
       so `.mockups-masonry .asset-container` descendant combinator is the
       reach-through-wrapper fix).
     - test-layout-triage-option-2a.html narrative line 89 (FIX D v2 —
       .space-container margin-bottom override; required because FIX A v2
       alone exposes inline negative margins as overlapping content at
       1-col stack).

   Why this chunk: at 820-991 the .mockups-masonry's 2-col zigzag
   aesthetic compresses each asset too narrowly to read; design intent
   is 1-col stacked. Surfaced via Phase II Preset 1 (iPad Air 834×1194)
   testing 2026-04-27 + cross-confirmed across 6 backup conversations
   (plan §4.6 audit). Note: plan §4.6 prescribed
   `flex-direction: column` mechanism from older backup; SUPERSEDED by
   triage's FIX A v2 (.asset-container flex-basis) which composes cleanly
   through the JS-injected .marquee-wrapper without `flex-direction`
   change at the container.

   Mechanism (FIX A v2 — zero !important):
   - Inline `style="width: calc(50% - 12px)"` on .asset-container in
     index.html carries specificity (1,0,0,0) for the width property only.
   - CSS `flex: 1 0 100%` (flex-basis) is a SEPARATE property from width;
     both apply to the element.
   - Per CSS Flexbox spec main-size resolution, explicit flex-basis wins
     over width for layout — so width stays declared as calc(50% - 12px)
     but flex-basis takes precedence at layout time.
   - No !important needed for FIX A v2.

   Mechanism (FIX D v2 — one !important, unavoidable):
   - Inline `style="...; margin-bottom: -36px"` (P1, 18 instances at
     index.html:275-412) / `-72px` (P2-P6, confirmed at index.html:585+)
     carries specificity (1,0,0,0) for the margin-bottom property.
   - No stylesheet selector chain can match (1,0,0,0) without an ID at
     root and even then only matches one column — !important is the only
     path to escape the inline cascade tier uniformly across all projects.
   - 48px = 8×6n (matches V3 design system spacing).
   - User-approved Q2 inclusion 2026-04-27; Phase 10.19 audit-tracked.
   - Without FIX D v2, FIX A v2 alone produces 1-col stacking with inline
     negative margins still active → items overlap (zero gap or worse).
     The pair is non-separable.

   Scope: 820-991 (MD Max) ONLY per triage source. LG (992-1199) and XL
   (1200+) preserve default 2-col flex-row rendering — re-evaluate LG
   handling at Phase II Preset 4 (LG Min 992×600) sweep before extending.

   P4 protection: this chunk's selector is `.mockups-masonry .asset-container`
   (specificity 0,2,0); existing `#project4 .asset-container` rules at
   v3-mockups-marquee.css:521+ are (1,1,0) — P4's custom 2-col rendering
   wins automatically via ID specificity without explicit exclusion.

   Composes with: V5 Direct Compression (iPad Air 820-1199 × ≥901h),
   V6 Tighter Mid-Column (820-1424 × ≤900h), V12 marquee, A3.7 title-break,
   and the new R4-CYCLING-TIMELINE-MD-PORT (above) — all at this scope band.

   To revert: search CLEAN-FIX-P5-S6.5c-R4-MASONRY-COLCOUNT-TRIAGE-PORT
   and delete everything between START and END markers.
   ============================================================================ */
@media (min-width: 820px) and (max-width: 991px) {
    .mockups-masonry .asset-container {
        flex: 1 0 100%;
        max-width: 100%;
    }
    .space-container {
        margin-bottom: 48px !important;
    }
}
/* END CLEAN-FIX-P5-S6.5c-R4-MASONRY-COLCOUNT-TRIAGE-PORT */


/* ============================================================================
   START CLEAN-FIX-P5-S6.5c-R4-OVERVIEW-TRIGGER-LEFT-ALIGN (2026-04-28)
   ============================================================================
   Universal removal of overview-trigger horizontal padding to align with
   sibling .project-info-column children.

   Surfaced via Phase II Preset 1 (iPad Air 834×1194) testing 2026-04-28
   + 3-agent review (ui-ninja design ✓, code-review-analyst CRITICAL bug
   catch on selector specificity, Plan agent strategy ✓).

   Root cause: V5 (line 3575), V6 (line 3649), and the rule at line 3914
   all set `.project-info-column .overview-trigger { padding: 12px 18px
   !important }`. The 18px horizontal component creates visible left-indent
   vs siblings (subtitle, impact, work-categories, project-module — all
   of which have NO horizontal padding in their respective scoped entries).
   User reports overview-trigger appearing offset from column-content edge.

   Fix: ungated override of horizontal padding components only. Vertical
   padding (12px top/bottom from V5/V6 shorthand) preserved.

   CRITICAL specificity correction (code-review-analyst 2026-04-28):
   - V5/V6/L3914 selectors are `.project-info-column .overview-trigger`
     with specificity (0,2,0).
   - Bare `.overview-trigger` (0,1,0) `!important` rule WOULD LOSE the
     specificity contest regardless of cascade order — `!important`-vs-
     `!important` is decided by selector specificity FIRST, then source
     order. This chunk uses matching `.project-info-column .overview-trigger`
     selector (0,2,0); equal specificity + equal `!important` resolved by
     source-order tie-breaker; tail-of-file placement wins.

   Per user direction 2026-04-28: apply universally (NOT scope-gated). Design-
   coherence with sibling alignment is universal — at every viewport where
   overview-trigger renders next to siblings without horizontal padding,
   overview-trigger should match. At scopes WITHOUT a `padding-left/right`
   rule on overview-trigger (XS/SM/MD-smaller mobile, default base) this
   rule is a no-op; only effective change is at V5/V6/L3914 scopes where
   18px horizontal was previously set.

   `!important` discipline: +2 active declarations (193 → 195) — JUSTIFIED
   per CLAUDE.md exception clause:
   - V5/V6/L3914 inline declarations use `!important`; matching `!important`
     is the only path to override at same specificity.
   - Alternative considered (raise specificity to ID-level): would conflict
     with V3 architecture's specificity-ladder convention.
   - Phase 10.19 audit-tracked alongside V5/V6/L3914 original `!important`
     uses; consolidation target: drop horizontal padding from V5/V6/L3914
     shorthand directly + delete this chunk.

   Cross-chunk note: this chunk relies on cascade-order tail-win. If a
   future chunk inserts AFTER this one with a `.project-info-column
   .overview-trigger` `padding-left/right` declaration, it would supersede.
   Phase 10.19 cleanup should consolidate before any such future addition.

   To revert: search CLEAN-FIX-P5-S6.5c-R4-OVERVIEW-TRIGGER-LEFT-ALIGN
   and delete everything between START and END markers.
   ============================================================================ */
.project-info-column .overview-trigger {
    padding-left: 0 !important;
    padding-right: 0 !important;
}
/* END CLEAN-FIX-P5-S6.5c-R4-OVERVIEW-TRIGGER-LEFT-ALIGN */

/* ============================================================================
   START CLEAN-FIX-P5-S7E-PHASE-CLICK-DOM-AUGMENT (V.5 phase-click PORT 2026-05-02)
   ============================================================================
   V.5 phase-click affordance — cursor: pointer + subtle hover state on phase
   labels at desktop scope (MD-larger / LG / XL). Mobile (XS/SM/MD-smaller) does
   NOT receive cursor (no phase-click on mobile; uses fallback marquee on P1/P6).

   768px breakpoint independent of V3CategoriesMarquee's 820px+ scope (different
   features: click-affordance vs marquee-scope; do NOT consolidate).

   Specificity (0,4,1) for cursor / (0,4,2) for hover — overrides any existing
   (0,4,0) .platform-stage .stage-label rules without requiring !important.
   ZERO new !important added.

   Companion edits in same chunk (CLEAN-FIX-P5-S7E-PHASE-CLICK-DOM-AUGMENT):
     - 12 data-phase-key="<LABEL>" attributes on .stage-label spans in index.html
       (P2 lines ~530/533/536, P3 ~968/971/974, P4 ~1464/1467/1470, P5 ~1819/1822/1825)
     - CLEAN-FIX-P5-S7E-PHASE-CLICK-MAPPING-CONVENTION comment in projectsData.js

   To revert this entire surface-prep chunk:
     1. Delete this CSS block (between START/END)
     2. Remove data-phase-key="X" attribute from 12 spans in index.html
        (search index.html for `data-phase-key=`)
     3. Delete the matching MAPPING-CONVENTION comment block in projectsData.js
        (search for CLEAN-FIX-P5-S7E-PHASE-CLICK-MAPPING-CONVENTION)
   ============================================================================ */
@media (min-width: 768px) {
    .project-info-column .project-timeline-horizontal .platform-stage .stage-label {
        cursor: pointer;
        /* No :hover { color: ... } rule — V3 custom cursor MORPH is the affordance signal.
           See CLEAN-FIX-P5-S7E-PHASE-CLICK-CURSOR-MORPH in v3-design-system.css for the
           visual treatment (combined O2+O3 per user decision 2026-05-02: shrink + per-project
           accent fill). The cursor: pointer here is a FALLBACK for when V3 custom cursor is
           inactive (touch device, JS error, reduced-motion, prefers-coarse-pointer). */
    }
    /* When V3 custom cursor is active (`html.cursor-active`), hide the system pointer so
       the cursor-morph IS the only visible cursor. Existing global rule
       `.cursor-active body *` at v3-design-system.css:740-748 has specificity (0,1,2) and
       loses to our (0,4,1) `cursor: pointer` above. This (0,5,1) override wins via the
       added `.cursor-active` ancestor class — no `!important` needed. */
    .cursor-active .project-info-column .project-timeline-horizontal .platform-stage .stage-label {
        cursor: none;
    }
}
/* END CLEAN-FIX-P5-S7E-PHASE-CLICK-DOM-AUGMENT */


