/**
 * Event Dashboard - structural stylesheet
 *
 * This file contains NO brand values. Every colour, font and radius comes from
 * a custom property defined in theme.css, which build.py generates from
 * config/brand.json. Edit brand.json, not this file.
 */

/**
 * @font-face {
 *   font-family: 'Your Brand Font';
 *   src: url('fonts/your-brand-font.woff2') format('woff2'),
 *        url('fonts/your-brand-font.woff') format('woff');
 *   font-weight: normal;
 *   font-style: normal;
 * }
 */

/* ================================================
   CSS VARIABLES & FOUNDATION
   ================================================ */

/* Brand tokens (:root) live in theme.css, generated from config/brand.json. */

/* Structural constants -- no brand values, so they belong here rather than in
   theme.css. The sidebar's rail and open widths are tokens because the nav's
   inner content is laid out at the OPEN width in both states (see the sidebar
   section); the two numbers have to agree or the rail reflows on every hover.
   The tablet/mobile media queries redefine them. */
:root {
    --sidebar-rail: 80px;
    --sidebar-open: 400px;
    /* Horizontal space the nav strips off the open width before the items:
       0.5rem of .nav-section padding each side + a stable 8px scrollbar gutter. */
    --nav-gutters: 24px;
    /* Insets that centre a fixed-size box in the rail, so the same element sits
       at one x in both states instead of sliding as the sidebar animates. */
    --rail-inset-28: calc((var(--sidebar-rail) - 28px) / 2);
    --rail-inset-32: calc((var(--sidebar-rail) - 32px) / 2);
    /* .nav-section's own side padding. The rail clip below has to subtract it to
       get from the row's box back to the rail's coordinates, so it lives here
       rather than as a literal in two places. */
    --nav-pad: 0.5rem;
    /* Painted width of a filled nav row in the rail: 12px clear of each rail
       edge. Concentric with the numbers, not with the row's box. */
    --rail-pill: calc(var(--sidebar-rail) - 24px);
}


/* Reset & Base Styles */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* Timestamps are <button> so they can seek the recording, but they must read as
   text, not as a form control. Declared HERE, before the component rules, on
   purpose: `.breakthrough-timestamp` / `.qa-timestamp` set their own size and
   colour and have to win, so this resets only the button chrome and inherits
   everything typographic. The clickable affordance is added further down, where
   it can override the component. */
.seek-link {
    -webkit-appearance: none;
    appearance: none;
    background: none;
    border: 0;
    padding: 0;
    font: inherit;
    color: inherit;
    letter-spacing: inherit;
    text-align: inherit;
    cursor: default;
}

body {
    font-family: var(--font-body);
    background-color: var(--light-gray);
    color: var(--text-primary);
    overflow-x: hidden;
}

/* ================================================
   LAYOUT STRUCTURE
   ================================================ */

.app-container {
    display: flex;
    height: 100vh;
    position: relative;
}

/* ================================================
   SIDEBAR STYLES
   ================================================ */

/**
 * The rail is a CLIP WINDOW, not a narrower layout.
 *
 * Everything inside the sidebar is laid out at --sidebar-open in both states and
 * simply clipped when the sidebar is 80px wide, so opening it animates one
 * number (the sidebar's own width) and reflows nothing. The earlier approach --
 * `display: none` on every label, un-hidden by the hover selector -- meant the
 * labels appeared at full text while the box was still 80px wide: every item
 * wrapped to two to four lines, the nav list grew 374px, the numbers were pushed
 * to a negative x, and the whole thing snapped back over the 300ms transition.
 * Measured before/after at 1440x900; see the sidebar notes in README.md.
 *
 * Consequence to keep in mind: labels are clipped rather than removed, so
 * anything inside the sidebar needs `overflow: hidden` on its own row.
 */
.sidebar {
    background: var(--white);
    border-right: 1px solid var(--medium-gray);
    transition: width 0.3s ease;
    display: flex;
    flex-direction: column;
    position: fixed;
    left: 0;
    top: 0;
    height: 100vh;
    z-index: 1000;
    box-shadow: var(--shadow-lg);
    overflow: hidden;
}

/* A sidebar carrying neither state class has no width of its own and sizes to
   its content. The markup always ships one and app.js keeps exactly one set,
   but pin the collapsed width here too so a missing class degrades to the
   narrow rail rather than a 370px-wide column of unlabelled numbers. */
.sidebar:not(.expanded) {
    width: var(--sidebar-rail);
}

.sidebar.collapsed {
    width: var(--sidebar-rail);
}

.sidebar.collapsed.peek {
    width: var(--sidebar-open);
}

.sidebar.expanded {
    width: var(--sidebar-open);
}

/* Labels fade rather than un-hiding. They stay in the layout (and in the
   accessibility tree, which `display: none` removed) and are clipped by the
   rail; opacity only stops them smearing under the header and footer borders
   as the width animates. */
.nav-text,
.nav-title,
.logo-expanded,
.we-goliath-text {
    transition: opacity 0.2s ease;
}

.sidebar:not(.expanded):not(.peek):not(.mobile-open) .nav-text,
.sidebar:not(.expanded):not(.peek):not(.mobile-open) .nav-title,
.sidebar:not(.expanded):not(.peek):not(.mobile-open) .we-goliath-text {
    opacity: 0;
}

/* Sidebar Header */
.sidebar-header {
    position: relative;   /* anchors the absolutely-placed toggle button */
    padding: 1rem;
    border-bottom: 1px solid var(--medium-gray);
    display: flex;
    align-items: center;
    justify-content: space-between;
    min-height: 80px;
    /* Updated Gradient: Blue to Purple */
    background: linear-gradient(135deg, var(--brand-dark), var(--brand-dark), var(--brand-primary));
}

/* The mark and the wordmark cross-fade in one cell. Stacking them absolutely is
   what keeps the header exactly 80px tall in both states -- as flow siblings the
   wordmark wrapped inside the 16px-wide rail container and shoved the toggle
   button 15px down the moment the labels appeared. */
.logo-container {
    position: relative;
    flex: 1;
    min-width: 0;
    height: 32px;
    overflow: hidden;
}

.logo-collapsed,
.logo-expanded {
    position: absolute;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    transition: opacity 0.2s ease;
}

/* Centred on the rail rather than pinned left, so the mark lines up with the
   agency icon in the footer instead of sitting 8px inboard of it. */
.sidebar:not(.expanded):not(.mobile-open) .logo-collapsed {
    left: calc(var(--rail-inset-32) - 1rem);
}

.logo-collapsed {
    display: flex;
    width: 32px;
    height: 32px;
    background: none;
    border-radius: 4px;
    align-items: center;
    justify-content: center;
    font-weight: bold;
    color: var(--white);
}

.logo-expanded {
    display: flex;
    flex-direction: column;
    width: max-content;
    opacity: 0;
}

.sidebar.expanded .logo-collapsed,
.sidebar.collapsed.peek .logo-collapsed,
.sidebar.mobile-open .logo-collapsed {
    opacity: 0;
}

.sidebar.expanded .logo-expanded,
.sidebar.collapsed.peek .logo-expanded,
.sidebar.mobile-open .logo-expanded {
    opacity: 1;
}

.logo-text,
.logo-title {
    white-space: nowrap;
}

.logo-text {
    color: var(--white);
    font-size: 0.55rem;
    font-weight: 300;
    letter-spacing: 0.05em;
    margin-bottom: 0.25rem;
}

.logo-title {
    color: var(--white);
    font-size: 0.875rem;
    font-weight: 800;
}

/* Taken OUT OF FLOW deliberately. The resting rail gives the header a 48px content
   box, and a 32px mark plus a 32px button needs 64px - so while the button was a
   flex sibling it squeezed .logo-container to 15px and (with that container
   clipping) cut the client's logo in half. Absolute means the container's width no
   longer depends on the button at all. */
.toggle-btn {
    position: absolute;
    right: 1rem;
    top: 50%;
    background: none;
    border: none;
    color: var(--white);
    cursor: pointer;
    padding: 0.5rem;
    border-radius: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    transform: translateY(-50%);
    transition: opacity 0.2s ease, background 0.3s ease;
    width: 32px;
    height: 32px;
}

/* translateY has to be repeated: a bare `scale()` here would replace it and drop
   the button half its height down the header. */
.toggle-btn:hover {
    background: rgba(255, 255, 255, 0.2);
    transform: translateY(-50%) scale(1.05);
}

/* In the resting rail there is only room for the logo, so the button steps aside.
   It is back the instant the sidebar widens - which is where you would reach for
   it - and hover is what widens it. */
.sidebar:not(.expanded):not(.peek):not(.mobile-open) .toggle-btn {
    opacity: 0;
    pointer-events: none;
}

.toggle-btn svg {
    width: 20px;
    height: 20px;
    transition: transform 0.3s;
}

.sidebar.expanded .toggle-btn svg {
    transform: rotate(180deg);
}

/* ================================================
   NAVIGATION STYLES
   ================================================ */

.nav-section {
    flex: 1;
    overflow-y: auto;
    /* The items are wider than the rail on purpose; clip them instead of
       offering a horizontal scrollbar. */
    overflow-x: hidden;
    /* Reserve the scrollbar's 8px in both states. The nav sits within a few
       pixels of overflowing at a 900px viewport, so without this the bar's
       appearance is itself a layout shift -- and the pinned item width below
       counts on the gutter being there. */
    scrollbar-gutter: stable;
    padding: var(--nav-pad);
    scrollbar-width: thin;
    scrollbar-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.02);
}

/* Custom Scrollbar */
.nav-section::-webkit-scrollbar {
    width: 8px;
}

.nav-section::-webkit-scrollbar-track {
    background: rgba(0, 0, 0, 0.02);
    border-radius: 4px;
}

.nav-section::-webkit-scrollbar-thumb {
    background: rgba(0, 0, 0, 0.1);
    border-radius: 4px;
}

.nav-section::-webkit-scrollbar-thumb:hover {
    background: rgba(0, 0, 0, 0.15);
}

/* Pinned to the open width so the heading never re-wraps; clipped in the rail. */
.nav-title {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--text-secondary);
    text-transform: uppercase;
    padding: 0.75rem 0.5rem 0.5rem;
    letter-spacing: 0.05em;
    width: calc(var(--sidebar-open) - var(--nav-gutters));
    white-space: nowrap;
}

/* Navigation Items
   Fixed width + flex-start is the whole trick: the row is laid out once, at the
   open width, so the label's line count -- and therefore the item's height and
   the position of every item below it -- cannot change when the sidebar
   animates. `justify-content: center` was actively harmful here: with content
   wider than the box it centres the OVERFLOW, which is what drove the numbers
   off the left edge of the screen mid-transition. */
.nav-item {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    width: calc(var(--sidebar-open) - var(--nav-gutters));
    /* Left pad puts the number's centre on the rail's centre line, so it holds
       one x in both states rather than sliding 6px. */
    padding: 0.625rem calc(var(--rail-inset-28) - 0.5rem);
    margin-bottom: 0.25rem;
    border-radius: 6px;
    cursor: pointer;
    transition: background 0.2s ease, color 0.2s ease, clip-path 0.3s ease;
    position: relative;
    overflow: hidden;
}

/* The rows stay pinned at the open width in both states (that is what stops the
   list reflowing), so a row carrying a fill -- Home, and whichever session is
   open -- has its right edge 296px off the rail and reads as a hard chop rather
   than a pill. Clip the paint back to the rail's usable width and round the cut.
   clip-path only affects painting, so the pinned width is untouched: no reflow,
   and the transition matches the sidebar's own 0.3s width animation. Rows with
   no fill look identical either way. Safe on ::after too, which sits at left:0. */
.sidebar:not(.expanded):not(.peek):not(.mobile-open) .nav-item {
    clip-path: inset(
        0
        calc(100% - (var(--sidebar-rail) / 2 - var(--nav-pad) + var(--rail-pill) / 2))
        0
        calc(var(--sidebar-rail) / 2 - var(--nav-pad) - var(--rail-pill) / 2)
        round 6px
    );
}

.nav-item:hover {
    background: var(--light-gray);
}

.nav-item.active {
    /* Updated Gradient: Blue -> Purple */
    background: linear-gradient(135deg, var(--brand-blue) 0%, var(--brand-green) 100%);
    color: var(--white);
}

/* Home is set apart from the numbered sessions -- heavier weight, a tint, its own
   gap below -- but it must NOT carry the selected fill while a session is open.
   It used to hold the full dark-to-primary gradient unconditionally, so opening a
   session left TWO rows looking selected and Home read as permanently current.
   The gradient now belongs to `.active`, which `showPage()` moves, so exactly one
   row is ever filled. */
/* Foreground is --brand-dark, NOT --brand-primary. The tint is near-white, and a
   primary that happens to be a bright accent fails against it -- CodePath's cyan
   measured 2.16:1 and Women of Bitcoin's pink 2.80:1. Every brand's dark clears
   10:1 here, so the label stays readable whatever the palette. */
.nav-item.intro-item {
    background: rgba(var(--brand-primary-rgb), 0.07);
    color: var(--brand-dark);
    font-weight: 600;
    margin-bottom: 0.75rem;
}

.nav-item.intro-item .nav-number {
    background: rgba(var(--brand-primary-rgb), 0.12);
    border-color: rgba(var(--brand-primary-rgb), 0.25);
    color: var(--brand-dark);
    font-size: 1rem;
}

/* Home while it IS the open page. Three classes, so this beats both
   `.nav-item.active` and `.nav-item.intro-item` regardless of source order --
   the pair above used to resolve by order alone, which is fragile. */
.nav-item.intro-item.active {
    background: linear-gradient(135deg, var(--brand-dark) 0%, var(--brand-primary) 100%);
    color: var(--white);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

/* --brand-dark on the white disc, matching what this rule did before it was split
   (it read --brand-purple, which is an alias of --brand-dark). A bright primary
   would leave the house glyph nearly invisible on white. */
.nav-item.intro-item.active .nav-number {
    background: rgba(255, 255, 255, 0.9);
    border-color: rgba(255, 255, 255, 0.5);
    color: var(--brand-dark);
}

/* Never shrinks and never moves: a fixed basis rather than min-width, because a
   shrinkable number is what let the rail squeeze it. */
.nav-number {
    flex: 0 0 28px;
    width: 28px;
    height: 28px;
    background: rgba(var(--brand-primary-rgb), 0.1);
    border: 1px solid rgba(var(--brand-primary-rgb), 0.2);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.8rem;
    font-weight: 500;
    margin-right: 0.75rem;
    color: var(--brand-purple);
    transition: all 0.2s;
}

.nav-item:hover .nav-number {
    background: rgba(var(--brand-primary-rgb), 0.2);
    border-color: rgba(var(--brand-primary-rgb), 0.4);
    color: var(--text-body);
}

.nav-item.active .nav-number {
    background: rgba(255, 255, 255, 0.9);
    border-color: rgba(255, 255, 255, 0.5);
    color: var(--brand-blue);
    font-weight: 600;
}

/* Resolves against the item's pinned width, so it wraps to the same number of
   lines in both states. min-width:0 keeps a long unbroken title from pushing the
   row wider than the item. */
.nav-text {
    font-size: 0.875rem;
    line-height: 1.2;
    flex: 1;
    min-width: 0;
    display: block;
}

/* ================================================
   SIDEBAR FOOTER
   ================================================ */

/* Side padding is the rail inset, not 1rem, so the icon is centred in the rail
   AND sits at the same x once the sidebar opens -- it used to slide 8px. */
.sidebar-footer {
    padding: 1rem var(--rail-inset-32);
    border-top: 1px solid var(--medium-gray);
    background: var(--light-gray);
    overflow: hidden;
}

.we-goliath-logo {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 0.75rem;
    width: calc(var(--sidebar-open) - var(--rail-inset-32) * 2);
}

.we-goliath-icon {
    flex: 0 0 32px;
    width: 32px;
    height: 32px;
    background: var(--brand-blue);
    border-radius: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 900;
    color: var(--gold-accent);
    font-size: 1.25rem;
}

.we-goliath-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.we-goliath-name,
.we-goliath-tagline {
    white-space: nowrap;
}

.we-goliath-name {
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--text-primary);
}

.we-goliath-tagline {
    font-size: 0.625rem;
    color: var(--text-secondary);
}

/* ================================================
   MAIN CONTENT AREA
   ================================================ */

/* 1136x350 is the design size, but as a FIXED width it overflowed the content
   column whenever the sidebar was pinned open (at 1440px the column is 1040px,
   so the banner was clipped and .main-content grew a horizontal scrollbar).
   max-width plus the same ratio as an aspect-ratio keeps the crop identical at
   the design size and scales it down instead of overflowing below it. */
.hero-banner {
  width: 100%;
  max-width: 1136px;
  aspect-ratio: 1136 / 350;
  border-radius: 12px;
  overflow: hidden; /* Clips the image to the container's shape */
  margin: 0 auto 2em auto; /* Centers the banner */
}

.hero-banner img {
  width: 100%;
  height: 100%;
  object-fit: cover; /* Makes the image cover the container without distortion */
}

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

.attribution-logo img{
width: 160px;
}

  /* No forced ratio on mobile: the container shrink-wraps whatever the client's
     banner actually is. Pinning 16/9 here cropped every hero we have ever
     shipped (both examples are 2.286:1, FlexFest is 3.246:1) -- a 3.25:1 banner
     lost ~45% of its width, i.e. both ends of the headline. */
  .hero-banner {
    width: 100%; /* Full width on mobile */
    height: auto; /* sized by the image's own aspect ratio */
    /* Must clear the desktop ratio, or it would crop here exactly the way the
       old 16/9 rule did. */
    aspect-ratio: auto;
    max-width: none;
    margin: 0 auto 1.75rem auto;
  }

  .hero-banner img {
    height: auto;
    object-fit: contain;
    display: block; /* kills the inline baseline gap under the banner */
  }

  /* The agency row is flex-start in every state now, so the override this block
     used to carry is gone rather than left as a dead !important. */
}

/* Only PINNING moves the content column; a hover-peek overlays it instead, which
   is deliberate -- reflowing the whole page on an accidental mouse-over is the
   one shift that would be worse than the sidebar's own. */
.main-content {
    flex: 1;
    margin-left: var(--sidebar-rail);
    transition: margin-left 0.3s ease;
    overflow-y: auto;
}

.sidebar.expanded ~ .main-content {
    margin-left: var(--sidebar-open);
}

.content-wrapper {
    max-width: 1200px;
    margin: 0 auto;
    padding: 2rem;
}

/* ================================================
   SESSION CONTENT STYLES
   ================================================ */

.session-header {
    background: var(--white);
    border-radius: 12px;
    padding: 1.5rem;
    margin-bottom: 2rem;
    box-shadow: var(--shadow-sm);
    display: flex;
    flex-direction: row-reverse;
    justify-content: space-between;
}

.maintitle{
    display: flex;
    justify-content: center;
}

.maintitle h1{
    font-size: 2.5rem;
}

.maintitle .session-meta{
    text-transform: uppercase;
}

.c1sesh{
    width: 20%;
    display: flex;
    justify-content: flex-end;
    align-items: center;
}

/* No font-family here: `.session-title` is listed in theme.css's heading rule,
   and this stylesheet loads after theme.css — re-declaring the body face here
   silently beat the client's display face on every session title. */
.session-title {
    font-size: 1.8rem;
    font-weight: 800;
    color: var(--text-primary);
    margin-bottom: 0.5rem;
}

.session-number {
    font-size: 0.875rem;
    font-weight: 300;
    margin-bottom: 0.5rem;
    text-transform: uppercase;
    color: var(--brand-blue);
}

.session-meta {
    color: var(--text-secondary);
    font-size: 0.875rem;
}

/* ================================================
   SPONSOR SECTION
   ================================================ */

.sponsor-section {
    background: var(--white);
    border-radius: 12px;
    padding: 2rem;
    margin: 2rem 0;
    box-shadow: var(--shadow-sm);
    text-align: center;
}

.sponsor-title {
    font-weight: 700;
    margin-bottom: 1.5rem;
    font-size: 1.25rem;
    position: relative;
    z-index: 10;
}

.sponsor-logos {
    background: var(--light-gray);
    border-radius: 8px;
    margin-bottom: 1rem; 
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 2rem;
    align-items: center;
    box-sizing: border-box;
    overflow: hidden;
    padding: 2rem; 
}

.sponsor-logo-link {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 150px;
    height: 70px;
    transition: transform 0.25s ease-in-out;
    box-sizing: border-box;
}

.sponsor-logo-link:hover {
    transform: scale(1.15);
}

.sponsor-logo-img {
    max-width: 100%;
    width: 200px;
    height: auto;
    max-height: 250px;
    object-fit: contain;
    display: block;
}

.sponsor-list {
    font-size: 0.875rem;
    color: var(--text-secondary);
    margin-top: 1rem;
}

@media (max-width: 600px) {
    .sponsor-logos {
        gap: 1.5rem;
    }
    .sponsor-logo-img {
        max-height: 80px;
    }
}

@media (max-width: 400px) {
    .sponsor-logos {
        gap: 1rem;
    }
    .sponsor-logo-img {
        max-height: 80px;
    }
}

/* ================================================
   CREDIT SECTION
   ================================================ */

.credit-section {
    /* Same vendored photo the attribution panel uses. This used to point at
       images/creditbg.jpg, WHICH DOES NOT SHIP - the panel only renders when
       agency.credit_headline is set, so no shipped config ever exercised the
       404 and white-on-white text it produced. The dark layer underneath is the
       real safety: the text stays readable even with the image missing. */
    background-color: var(--brand-dark);
    background-image: url('images/attribution-bg.jpeg');
    background-size: cover;
    background-position: center;
    border-radius: 12px;
    padding: 2rem;
    margin-top: 2rem;
    text-align: center;
    color: var(--white);
}

.credit-logo {
    display: inline-flex;
    align-items: center;
    gap: 1rem;
}

.credit-logo-icon {
    width: 40px;
    height: 40px;
    background: transparent;
    border: 2px solid var(--gold-accent);
    border-radius: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 900;
    color: var(--gold-accent);
    font-size: 1.5rem;
}

.credit-text {
    text-align: left;
}

.credit-name {
    font-weight: 700;
    font-size: 1.125rem;
}

.credit-tagline {
    font-size: 0.875rem;
    opacity: 0.9;
}

.credit-description {
    margin: 1.5rem 0;
    opacity: 0.95;
}

/* ================================================
   VIDEO SECTION
   ================================================ */

.video-section {
    background: var(--white);
    border-radius: 12px;
    padding: 1.5rem;
    margin-bottom: 2rem;
    box-shadow: var(--shadow-sm);
}

.video-tabs {
    display: flex;
    gap: 0.5rem;
    margin-bottom: 1.5rem;
    border-bottom: 2px solid var(--medium-gray);
}

.video-tab {
    padding: 0.75rem 1.5rem;
    background: transparent;
    border: none;
    color: var(--text-secondary);
    font-weight: 500;
    cursor: pointer;
    position: relative;
    transition: all 0.2s;
    font-family: inherit;
}

.video-tab:hover {
    color: var(--text-primary);
}

.video-tab.active {
    color: var(--brand-blue);
}

.video-tab.active::after {
    content: '';
    position: absolute;
    bottom: -2px;
    left: 0;
    right: 0;
    height: 2px;
    background: var(--brand-blue);
}

.video-container {
    position: relative;
    width: 100%;
    padding-bottom: 56.25%;
    height: 0;
    overflow: hidden;
    background: var(--video-placeholder-bg);
    border-radius: 8px;
}

.video-placeholder {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--white);
}

.video-container iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    border: 0;
}

/* ================================================
   SPEAKER INFO DROPDOWN
   ================================================ */

.speaker-info {
    background: var(--light-gray);
    border-radius: 8px;
    margin-top: 1.5rem;
    overflow: hidden;
    transition: all 0.3s;
}

/* A card holding only the speaker panel (a session whose line-up is confirmed
   but whose recording is not up yet) has nothing above it to clear. */
.video-section.speaker-only .speaker-info {
    margin-top: 0;
}

.speaker-toggle {
    width: 100%;
    padding: 1rem 1.5rem;
    background: transparent;
    border: none;
    display: flex;
    justify-content: space-between;
    align-items: center;
    cursor: pointer;
    font-weight: 600;
    color: var(--text-primary);
    font-family: inherit;
}

.speaker-toggle:hover {
    background: rgba(0, 0, 0, 0.02);
}

.speaker-content {
    display: grid;
    grid-template-rows: 0fr; 
    overflow: hidden; 
    transition: grid-template-rows 0.3s ease-out;
}

.speaker-info.expanded .speaker-content {
    grid-template-rows: 1fr;
    padding: 1.5rem 1.5rem;
}

.speaker-details {
    display: grid;
    gap: 1rem;
    overflow: hidden;
}

.speaker-field {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.speaker-label {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.speaker-value {
    color: var(--text-primary);
    line-height: 1.6;
    font-size: clamp(0.9rem, 2vi + 0.5rem, 1rem);
}

.chevron {
    transition: transform 0.3s;
}

.speaker-info.expanded .chevron {
    transform: rotate(180deg);
}

/* ================================================
   TAKEAWAYS SECTION
   ================================================ */

.takeaways-section {
    background: var(--white);
    border-radius: 12px;
    padding: 2rem;
    margin-bottom: 2rem;
    box-shadow: var(--shadow-sm);
}

/* Content Tabs */
.content-tabs {
    display: flex;
    gap: 0.5rem;
    margin-bottom: 1.5rem;
    border-bottom: 2px solid var(--medium-gray);
}

.content-tab {
    padding: 0.875rem 1.5rem;
    background: transparent;
    border: none;
    color: var(--text-secondary);
    font-weight: 500;
    cursor: pointer;
    position: relative;
    transition: all 0.2s;
    font-family: inherit;
    font-size: 0.95rem;
}

.content-tab:hover {
    color: var(--text-primary);
}

.content-tab.active {
    color: var(--brand-blue);
}

.content-tab.active::after {
    content: '';
    position: absolute;
    bottom: -2px;
    left: 0;
    right: 0;
    height: 2px;
    background: var(--brand-blue);
}

.tab-content {
    display: none;
}

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

.takeaways-header {
    border-bottom: 2px solid var(--medium-gray);
    padding-bottom: 1rem;
    margin-bottom: 2rem;
}

.takeaways-title {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--text-primary);
}

/* ================================================
   CONTENT COMPONENTS
   ================================================ */

/* Section Boxes */
.section-box {
    background: var(--light-gray);
    border-radius: 8px;
    padding: 1.5rem;
    margin-top: 1.5rem;
}

.section-box-title {
    font-size: 1rem;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 1rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.section-box-title::before {
    content: '';
    width: 4px;
    height: 20px;
    /* Updated gradient: Green to Blue */
    background: linear-gradient(180deg, var(--brand-green), var(--brand-blue));
    border-radius: 2px;
}

/* Breakthrough Items */
.breakthrough-item {
    background: var(--white);
    border-radius: var(--border-radius);
    padding: 1.5rem;
    margin-bottom: 1.5rem;
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--medium-gray);
}

.breakthrough-title {
    font-size: 1.125rem;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 1rem;
}

.breakthrough-timestamp {
    font-size: 0.875rem;
    color: var(--text-secondary);
    font-weight: 400;
}

.breakthrough-content {
    margin: 1rem 0;
}

.breakthrough-label {
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 0.5rem;
}

.example-box .breakthrough-label {
    font-size: 16px;
}

.breakthrough-text {
    color: var(--text-body);
    line-height: 1.7;
    margin-bottom: 1rem;
}

/* Action Lists */
.action-list {
    list-style: none;
    display: grid;
    gap: 1rem;
    line-height: 1.7;
}

.action-item {
    font-size: clamp(0.9rem, 2vi + 0.5rem, 1rem);
    padding-left: 1.5rem;
    position: relative;
    color: var(--text-primary);
}

.action-item::before {
    content: '→';
    position: absolute;
    left: 0;
    color: var(--brand-green); /* Updated to Green arrow */
    font-weight: 600;
}

/* Quote Boxes */
.quote-box {
    /* Updated background tint to Blue/Purple */
    background: linear-gradient(135deg, rgba(var(--brand-primary-rgb), 0.05), rgba(var(--brand-secondary-rgb), 0.05));
    border-left: 4px solid var(--brand-blue);
    padding: 1rem 1.5rem;
    margin: 1rem 0;
    border-radius: 0 8px 8px 0;
    font-style: italic;
    color: var(--text-primary);
    font-size: clamp(0.9rem, 2vi + 0.5rem, 1rem);
}

.quote-author {
    text-align: right;
    margin-top: 0.5rem;
    font-size: 0.875rem;
    color: var(--text-secondary);
    font-style: normal;
}

/* Call-to-Action Button */
.cta-button {
    display: inline-block;
    padding: 0.75rem 2rem;
    /* Updated Gradient: Blue to Green */
    background: linear-gradient(90deg, var(--brand-blue), var(--brand-green));
    color: var(--white);
    text-decoration: none;
    border-radius: 6px;
    font-weight: 600;
    transition: all 0.3s;
    margin-top: 1rem;
}

.cta-button:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-lg);
}

/* ================================================
   RECALL CARDS SECTION
   ================================================ */

.recall-embed {
    background: var(--light-gray);
    padding: 1rem;
    border-radius: 12px;
    /* Per-session override: the build sets --recall-height on this element from
       recall.height, so a short deck does not leave a screen of empty grey. */
    height: var(--recall-height, 75vh);
}

.recall-embed iframe {
    width: 100%;
    height: 100%; /* Fill the container */
    border: none;
}

.recall-placeholder {
    text-align: center;
    padding: 3rem;
    color: var(--text-secondary);
}

/* ================================================
   STAR RATING SYSTEM
   ================================================ */

.star-rating {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    margin-bottom: 1rem;
    justify-content: center;
}

.star {
    font-size: 2rem;
    color: var(--star-inactive);
    cursor: pointer;
    transition: color 0.2s, transform 0.12s;
    background: none;
    border: 0;
    padding: 0;
    line-height: 1;
}

/* Two states, both driven by app.js adding a class - never an inline style.
   .is-preview is the hover/focus fill and outranks .is-filled so dragging the
   pointer left below a committed rating actually shows the lower value. */
.star.is-filled {
    color: var(--star-active);
}

.star-rating.is-previewing .star {
    color: var(--star-inactive);
}

.star-rating.is-previewing .star.is-preview {
    color: var(--star-active);
}

.star:hover,
.star:focus-visible {
    transform: scale(1.12);
}

.star:focus-visible {
    outline: 2px solid var(--brand-primary);
    outline-offset: 2px;
    border-radius: 4px;
}

/* ================================================
   PAGE CONTENT MANAGEMENT
   ================================================ */

.page-content {
    display: none;
}

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

/* ================================================
   EVENT HEADER BANNER
   ================================================ */

.event-banner {
  position: relative;
  background:
    radial-gradient(1000px 500px at -10% -10%, rgba(var(--brand-secondary-rgb), 0.18), transparent 60%),
    radial-gradient(800px 400px at 110% -10%, rgba(var(--brand-primary-rgb), 0.22), transparent 60%),
    linear-gradient(135deg, var(--brand-dark), var(--brand-dark-soft) 100%);
  border-radius: var(--border-radius);
  padding: clamp(28px, 4vw, 48px);
  color: var(--white);
  box-shadow: var(--shadow-md);
  overflow: hidden;
  isolation: isolate;
  margin-bottom: 2em;
}

.event-banner::after {
  content: "";
  position: absolute; inset: -30px -30px auto auto;
  width: 320px; height: 320px; border-radius: 50%;
  background: conic-gradient(from 180deg, var(--brand-orange), var(--brand-green), var(--brand-blue), var(--brand-purple), var(--brand-orange));
  filter: blur(60px); opacity: .25; pointer-events: none; z-index: -1;
}

.event-banner-content h1 {
  font-size: clamp(28px, 5vw, 46px);
  line-height: 1.05;
  letter-spacing: .02em;
  margin: 0 0 8px;
  font-weight: 900;
}
.event-banner-content h1 span { color: var(--brand-green); }
.event-banner-subtitle {
  font-weight: 600; opacity: .95; margin-bottom: 8px;
}
.event-banner-date {
  font-size: 13px; opacity: .85; letter-spacing: .06em;
  text-transform: uppercase;
}
.event-banner-line {
  height: 2px; width: 100%; max-width: 280px; margin-top: 16px;
  background: linear-gradient(90deg, var(--brand-green), transparent);
  opacity: .8; border-radius: 2px;
}

/* Interactive spotlight effect on hero */
.event-banner {
  position: relative;
  overflow: hidden;
}
.event-banner::before {
  content: "";
  position: absolute;
  width: 400px; height: 400px;
  border-radius: 50%;
  background: radial-gradient(circle at center, rgba(255,255,255,0.12), transparent 70%);
  pointer-events: none;
  transform: translate(-50%, -50%);
  top: var(--mouse-y, 50%);
  left: var(--mouse-x, 50%);
  transition: top .05s linear, left .05s linear;
  z-index: 1;
}

/* Entrances */
.event-banner,
.section-box,
.session-header,
.video-section,
.takeaways-section,
.sponsor-section,
.credit-section,
.attribution-section,
.rating-section,
.feedback-form {
  animation: popIn .38s cubic-bezier(.22,.85,.31,1) both;
}



/* ================================================
   HERO "SPOTLIGHT" — mouse-follow effect
   (JS sets --mx and --my as percentages)
   ================================================ */
.event-banner {
  position: relative;
  --mx: 50%;
  --my: 50%;
  --parallaxX: 0px;
  --parallaxY: 0px;
}

.event-banner::before {
  content: "";
  position: absolute; inset: 0;
  background:
    radial-gradient(340px 340px at var(--mx) var(--my),
      rgba(var(--brand-primary-rgb), 0.18), transparent 60%);
  mix-blend-mode: screen;
  pointer-events: none;
  transition: opacity .35s ease;
  z-index: 0;
}

/* Layer management so content stays above spotlight */
.event-banner > * { position: relative; z-index: 1; }

/* Subtle parallax on the hero content */
.event-banner .event-banner-content {
  will-change: transform;
  transform: translate3d(var(--parallaxX), var(--parallaxY), 0);
  transition: transform .08s linear;
}

/* Optional glossy line shimmer on load */
.event-banner-line {
  background-image: linear-gradient(90deg, rgba(255,255,255,.2), rgba(255,255,255,0) 50%, rgba(255,255,255,.2));
  background-size: 200% 100%;
  animation: shimmer 1.8s ease .3s both;
}



/* ================================================
   HOW TO USE SECTION
   ================================================ */

.how-to-use-section {
    background: var(--white);
    border-radius: 12px;
    padding: 2rem;
    margin-bottom: 2rem;
    box-shadow: var(--shadow-sm);
}

.how-to-use-title {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 1.5rem;
   text-align: center;
}

.how-to-use-list {
    display: grid;
    gap: 1rem;
}

.how-to-use-item {
    padding-left: 1.5rem;
    position: relative;
}

.how-to-use-item::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0.5rem;
    width: 6px;
    height: 6px;
    background: var(--brand-green);
    border-radius: 50%;
}

/* ================================================
   SESSION SPECIFIC STYLES
   ================================================ */

.back-button {
    background: transparent;
    border: 1px solid var(--brand-blue);
    color: var(--brand-blue);
    padding: 0.5rem 1rem;
    border-radius: 6px;
    font-size: 0.875rem;
    cursor: pointer;
    transition: all 0.2s;
    font-family: inherit;
    margin-bottom: 1rem;
}

.back-button:hover {
    background: var(--brand-blue);
    color: var(--white);
}

/* Big Picture Section */
.big-picture-section {
    background: linear-gradient(135deg, rgba(var(--brand-primary-rgb), 0.05), rgba(var(--brand-secondary-rgb), 0.05));
    border-left: 4px solid var(--brand-blue);
    padding: 1.5rem;
    border-radius: 0 8px 8px 0;
    margin-bottom: 2rem;
}

.big-picture-text {
    line-height: 1.8;
}

/* Breakthrough Sections */
.breakthrough-insights {
    margin-top: 2rem;
}

.breakthrough-insights h3 {
    font-size: 1.5rem;
    font-weight: 700;
    margin-bottom: 1.5rem;
}

.core-question-box {
    padding: 1rem;
    background: var(--light-gray);
    border-radius: 8px;
    margin: 1rem 0 1.7rem 0;
}

.core-question-text {
    font-style: italic;
    color: var(--text-body);
}

.action-step-box {
    padding-left: 1rem;
    border-left: 3px solid var(--brand-green);
}

.example-box {
    border-radius: 8px;
    margin-top: 1rem;
    margin-bottom: 1rem;
}

/* Q&A Styles */
.qa-item {
    margin-bottom: 1.5rem;
    padding-bottom: 1.5rem;
    border-bottom: 1px solid var(--medium-gray);
}

.qa-question {
    font-weight: 600;
    color: var(--primary-navy);
    margin-bottom: 0.5rem;
}

.qa-timestamp {
    font-size: 0.875rem;
    color: var(--text-secondary);
    font-weight: 400;
}

/* ================================================
   TIMESTAMP SEEK LINKS
   ================================================ */

/* Only an ENABLED seek link looks clickable. app.js enables them per session, and
   only where a full-session recording exists, so a dashboard published before the
   videos are cut renders these as the plain text they have always been -- no dead
   affordances promising something that does nothing.

   These rules sit after the timestamp components deliberately: the reset near the
   top of the file inherits the component's size and colour, and this is the part
   that is meant to override it. */
.seek-link:not(:disabled) {
    cursor: pointer;
    color: var(--brand-primary);
    text-decoration-line: underline;
    text-decoration-style: dotted;
    text-underline-offset: 2px;
    border-radius: 3px;
    transition: color 0.15s ease, background-color 0.15s ease;
}

.seek-link:not(:disabled):hover,
.seek-link:not(:disabled):focus-visible {
    color: var(--brand-dark);
    background-color: rgba(var(--brand-primary-rgb), 0.1);
    text-decoration-style: solid;
}

.seek-link:not(:disabled):focus-visible {
    outline: 2px solid var(--brand-primary);
    outline-offset: 2px;
}

/* The quote attribution has no timestamp component of its own, so this only needs
   to hold the line against the surrounding italics. */
.quote-timestamp {
    font-style: normal;
}

/* A 14px timestamp is a 20px-tall tap target, which is half what a thumb needs.
   Padded out on small screens, and only when ENABLED so a dashboard with no
   recordings keeps the spacing it has always had. On the inline timestamps the
   padding grows the hit area without changing line height; the breakthrough one
   is display:block here, so it takes a real min-height and is pulled back level
   with the text it sits under. */
@media (max-width: 768px) {
    .seek-link:not(:disabled) {
        padding: 0.375rem 0.25rem;
    }

    .breakthrough-timestamp.seek-link:not(:disabled) {
        min-height: 44px;
        padding: 0.625rem 0.5rem;
        margin-left: -0.5rem;
        display: flex;
        align-items: center;
        width: fit-content;
    }
}

.qa-answer {
    color: var(--text-primary);
    line-height: 1.7;
    padding-left: 1rem;
}

/* Call to Action */
.cta-section {
    text-align: center;
    margin-top: 2rem;
    padding: 2rem;
    background: linear-gradient(135deg, rgba(var(--brand-primary-rgb), 0.05), rgba(var(--brand-secondary-rgb), 0.05));
    border-radius: var(--border-radius);
}

.cta-text {
    margin-bottom: 1rem;
    font-size: 1.125rem;
}

/* Rating Section */
.rating-section {
    background: var(--white);
    border-radius: var(--border-radius);
    padding: 2rem;
    margin-top: 2rem;
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--medium-gray);
    text-align: center;
}

.rating-title {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 1rem;
}

.rating-description {
    color: var(--text-secondary);
    margin-bottom: 1.5rem;
    line-height: 1.6;
}

.rating-instructions {
    font-size: 0.875rem;
    color: var(--text-secondary);
}

.rating-text {
    margin-left: 1rem;
    font-weight: 600;
    color: var(--text-secondary);
}

/* Feedback Form */
.feedback-form {
    background: var(--white);
    border-radius: var(--border-radius);
    padding: 2rem;
    margin-top: 2rem;
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--medium-gray);
}

.feedback-header {
    text-align: center;
    margin-bottom: 2rem;
}

.feedback-title {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 1rem;
}

.feedback-subtitle {
    color: var(--text-secondary);
    line-height: 1.6;
}

.feedback-grid {
    display: grid;
    gap: 1rem;
}

.feedback-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
}

.feedback-field label {
    display: block;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 0.5rem;
}

.feedback-input {
    width: 100%;
    padding: 0.75rem;
    border: 1px solid var(--medium-gray);
    border-radius: 6px;
    font-size: 0.875rem;
    transition: border-color 0.2s;
    font-family: var(--font-body);
}

.feedback-textarea {
    width: 100%;
    padding: 0.75rem;
    border: 1px solid var(--medium-gray);
    border-radius: 6px;
    font-size: 0.875rem;
    resize: vertical;
    transition: border-color 0.2s;
    font-family: var(--font-body);
}

.feedback-submit-container {
    text-align: center;
    margin-top: 1rem;
}

.feedback-submit {
    background: var(--brand-blue);
    color: var(--white);
    border: none;
    padding: 0.75rem 2rem;
    border-radius: 6px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.3s;
    font-size: 0.95rem;
}

.feedback-submit:hover {
    transform: translateY(-1px);
    box-shadow: var(--shadow-md);
}

/* We & Goliath Attribution
   The background ships in assets/images/ and is copied into every build. It used
   to hotlink https://i.imgur.com/REvEMRY.jpeg -- a remote dependency inside a
   deliverable that is otherwise a self-contained folder, so every dashboard we
   had ever handed over would have lost this panel the day that link went away. */
.attribution-section {
    background-image: url('images/attribution-bg.jpeg');
    background-size: cover;
    background-position: center;
    border-radius: var(--border-radius);
    padding: 2rem;
    margin-top: 2rem;
    text-align: center;
    color: var(--white);
}

.attribution-logo {
    display: inline-flex;
    align-items: center;
    gap: 1rem;
    margin-bottom: 1.0rem;
    flex-direction: column;
}

.attribution-icon {
    width: 40px;
    height: 40px;
    background: transparent;
    border: 2px solid var(--gold-accent);
    border-radius: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 900;
    color: var(--gold-accent);
    font-size: 1.5rem;
}

.attribution-text {
    text-align: left;
}

.attribution-name {
    font-weight: 700;
    font-size: 1.125rem;
}

.attribution-tagline {
    font-size: 0.875rem;
    opacity: 0.9;
}

.attribution-description {
    margin-bottom: -10px;
    width: 70%;
    margin-top: 0.4em;
    opacity: 0.95;
    line-height: 1.6;
}

.attribution-cta {
    display: inline-block;
    padding: 0.75rem 2rem;
    background: var(--brand-secondary);
    color: white;
    text-decoration: none;
    border-radius: 6px;
    font-weight: 600;
    transition: all 0.3s;
}

.attribution-cta:hover {
    transform: translateY(-1px);
    box-shadow: var(--shadow-md);
}

/* Coming Soon Placeholder */
.coming-soon {
    background: var(--white);
    border-radius: 12px;
    padding: 3rem;
    box-shadow: var(--shadow-sm);
    text-align: center;
}

.coming-soon p {
    color: var(--text-secondary);
}

/* ================================================
   MODAL STYLES
   ================================================ */

.modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.6);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 2000;
    opacity: 0;
    transition: opacity 0.3s ease;
    pointer-events: none;
}

.modal-overlay:target,
.modal-overlay.visible {
    opacity: 1;
    pointer-events: auto;
}

.modal-box {
    background: var(--white);
    padding: 2rem;
    border-radius: var(--border-radius);
    box-shadow: var(--shadow-lg);
    width: 90%;
    max-width: 400px;
    text-align: center;
    transform: scale(0.95);
    transition: transform 0.3s ease;
}

.modal-overlay:target .modal-box,
.modal-overlay.visible .modal-box {
    transform: scale(1);
}

.modal-box p {
    margin-bottom: 1.5rem;
    color: var(--text-primary);
    line-height: 1.6;
}

.modal-close-btn {
    background: linear-gradient(90deg, var(--brand-blue), var(--brand-purple));
    color: var(--white);
    border: none;
    padding: 0.75rem 1.5rem;
    border-radius: 6px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.3s;
    font-size: 0.95rem;
}

.modal-close-btn:hover {
    box-shadow: var(--shadow-md);
}


/* ================================================
   RESPONSIVE DESIGN
   ================================================ */

/* Mobile Overlay */
.mobile-overlay {
    display: none; /* Hidden by default */
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.5);
    z-index: 999;
    opacity: 0;
    transition: opacity 0.3s ease;
}

/* Becomes visible when the menu is open */
.mobile-overlay.active {
    display: block;
    opacity: 1;
}

/* Mobile Header */
.mobile-header {
    display: none; /* Hidden on desktop */
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 60px;
    background: var(--white);
    border-bottom: 1px solid var(--medium-gray);
    z-index: 1001;
    align-items: center;
    padding: 0 1rem;
    box-shadow: var(--shadow-sm);
}

.mobile-menu-toggle {
    background: none;
    border: none;
    cursor: pointer;
    padding: 0.5rem;
    display: flex;
    flex-direction: column;
    justify-content: space-around;
    width: 30px;
    height: 30px;
}

.hamburger-line {
    width: 25px;
    height: 3px;
    background: var(--text-primary);
    border-radius: 2px;
    transition: all 0.3s ease-in-out;
}

/* "X" animation for the hamburger icon */
.mobile-menu-toggle.active .hamburger-line:nth-child(1) {
    transform-origin: center;
    transform: translateY(6px) translateX(-3px) rotate(45deg) !important;
}
.mobile-menu-toggle.active .hamburger-line:nth-child(2) {
    opacity: 0 !important;
}
.mobile-menu-toggle.active .hamburger-line:nth-child(3) {
    transform-origin: center;
    transform: translateY(-4px) translateX(-3px) rotate(-45deg) !important;
}

.mobile-back-button {
  display: none; /* Hidden by default */
  background: none;
  border: solid 1px var(--brand-blue);
  font-size: 0.8rem;
  color: var(--brand-blue);
  font-weight: 400;
  cursor: pointer;
  padding: 0.5rem;
  border-radius: 4px;
}


/* --- This is the key section for mobile view --- */
@media (max-width: 768px) {
    .mobile-header {
        display: flex;
        justify-content: space-between; /* Pushes items to ends */
        align-items: center;
    }

    .mobile-header-right {
      display: flex;
      align-items: center;
      gap: 0.5rem; /* Adds a small space between the back button and logo */
    }

    .mobile-logo{
        display: flex;
        align-items: center;
        margin-bottom: 1px;
    }

    .mobile-logo a{
        display: flex;
        align-items: center;
    }
    
    /* The drawer is narrower than the desktop panel, so the token has to follow
       or the pinned nav rows (sized from --sidebar-open) would be clipped by
       76px and lose the end of every session title. */
    :root {
        --sidebar-open: 300px;
    }

    .sidebar {
        position: fixed;
        width: 300px !important; /* Set a fixed width for the slide-out menu */
        height: 100vh;
        top: 0;
        left: 0;
        transform: translateX(-100%); /* Start off-screen */
        transition: transform 0.3s ease-in-out;
        z-index: 1000;
    }

    .sidebar-header {
         display: none;
      }

/* When a session page is active, show the new back button */
  body.session-active .mobile-back-button {
    display: block;
  }

  /* Hide the original back button on mobile view */
  .session-header .back-button {
    display: none;
  }


/* Add padding to the top of the session list to clear the mobile header */
  .sidebar .nav-section {
    padding-top: 60px;
  }
    
    /* This class makes the sidebar visible */
    .sidebar.mobile-open {
        transform: translateX(0); /* Slide into view */
    }

    .sidebar.mobile-open .nav-number {
        margin-right: 1rem !important;
    }

    
    .main-content {
        margin-left: 0 !important; /* Main content takes full width */
        padding-top: 60px; /* Avoid content going under the fixed header */
    }

    /* Labels are opacity-driven now, so the drawer reveals them by fading rather
       than by forcing `display` -- which used to flatten .logo-expanded and
       .we-goliath-text out of their flex column. The .mobile-open cases are
       already handled where those rules live; nothing to force here. */

}

/* Tablet Styles */
@media (max-width: 1024px) and (min-width: 769px) {
    /* Tablet runs a narrower rail and a narrower panel; both tokens follow so the
       rail insets still centre and the nav rows still match the open width. */
    :root {
        --sidebar-rail: 60px;
        --sidebar-open: 300px;
    }

    /* No width or margin overrides belong here. Redefining the two tokens above
       is the whole job: `.sidebar.collapsed`, `.sidebar.expanded` and
       `.main-content` all resolve through them, so tablet gets 60/300 for free.

       This block used to hard-code `width: 60px !important` on `.sidebar`, an
       unscoped `:hover` at `300px !important`, and `margin-left: 60px !important`
       on `.main-content`. Three bugs came out of that:
         - `!important` on the base rule outranked `.sidebar.expanded`, so the
           pin button could never widen the rail on a tablet -- but it still
           added `.expanded`, which dropped the rail clip and un-hid the labels.
           A 276px-wide filled row then painted inside a 60px rail.
         - the pinned margin outranked `.sidebar.expanded ~ .main-content`, so
           the content never moved and the open sidebar covered it by 240px.
         - the hover rule was not scoped to `.collapsed` the way the desktop one
           is, so it also fired while pinned.
       Change a sidebar width ONLY through --sidebar-rail / --sidebar-open. */
    .content-wrapper {
        padding: 1.5rem;
    }
}

/* Mobile Specific Styles */
@media (max-width: 768px) {
    .content-wrapper {
        padding: 1rem 0.75rem;
    }
    
    /* Event Banner Mobile */
    .event-banner {
        padding: 2rem 1rem;
        margin-bottom: 1.5rem;
    }
    
    .event-banner h1 {
        font-size: 1.75rem;
        line-height: 1.2;
    }
    
    .event-banner h1 span {
        font-size: 1.5rem;
    }
    
    .event-banner-subtitle {
        font-size: 1.125rem;
    }
    
    .event-banner-date {
        font-size: 1rem;
    }
    
    /* Session Header Mobile */
    .session-header {
        padding: 1rem;
        margin-bottom: 1.5rem;
        flex-direction: column;
    }
    
    .session-title {
        font-size: 1.25rem;
        line-height: 1.3;
    }

.attribution-description {
    width: 100%;
}
    
    /* Video Section Mobile */
    .video-section {
        padding: 1rem;
    }
    
    .video-tabs {
        margin-bottom: 1rem;
    }
    
    .video-tab {
        padding: 0.625rem 1rem;
        font-size: 0.875rem;
    }
    
    /* Speaker Info Mobile */
    .speaker-toggle {
        padding: 0.875rem 1rem;
        font-size: 0.875rem;
    }
    
    .speaker-content {
        padding: 0 1rem;
    }
    
    .speaker-info.expanded .speaker-content {
        padding: 1rem 1rem;
    }
    
    /* Takeaways Section Mobile */
    .takeaways-section {
        padding: 1rem;
    }
    
    .content-tabs {
        padding: 0;
        flex-wrap: wrap;
        gap: 0;
    }
    
    .content-tab {
        padding: 0.75rem 1rem;
        font-size: 0.875rem;
        min-width: 0;
        flex: 1;
        text-align: center;
    }
    
    /* Breakthrough Items Mobile */
    .breakthrough-item {
        padding: 1rem;
        margin-bottom: 1rem;
    }
    
    .breakthrough-title {
        font-size: 1rem;
        line-height: 1.4;
    }
    
    .breakthrough-timestamp {
        display: block;
        margin-top: 0.25rem;
    }
    
    /* Section Boxes Mobile */
    .section-box {
        padding: 1rem;
        margin-top: 1rem;
    }
    
    .section-box-title {
        font-size: 0.95rem;
    }
    
    /* Quote Boxes Mobile */
    .quote-box {
        padding: 0.875rem 1rem;
        font-size: 0.9rem;
    }
    
    /* Big Picture Section Mobile */
    .big-picture-section {
        padding: 1rem;
    }
    
    .big-picture-text {
        font-size: 0.95rem;
        line-height: 1.6;
    }
    
    /* Feedback Form Mobile */
    .feedback-form {
        padding: 1rem;
    }
    
    .feedback-row {
        grid-template-columns: 1fr;
        gap: 1rem;
    }
    
    .feedback-input,
    .feedback-textarea {
        font-size: 16px; /* Prevents zoom on iOS */
    }
    
    .feedback-submit {
        padding: 0.875rem 1.5rem;
        font-size: 0.875rem;
        width: 100%;
    }
    
    /* Rating Section Mobile */
    .rating-section {
        padding: 1.5rem 1rem;
    }
    
    .star-rating {
        justify-content: center;
        flex-wrap: wrap;
        gap: 0.25rem;
    }
    
    .star {
        font-size: 1.75rem;
    }
    
    .rating-text {
        margin-left: 0;
        margin-top: 0.5rem;
        width: 100%;
        text-align: center;
    }
    
    /* Attribution Section Mobile */
    .attribution-section,
    .credit-section {
        padding: 1.5rem 1rem;
    }
    
    .attribution-logo,
    .credit-logo {
        flex-direction: column;
        text-align: center;
        gap: 0.75rem;
    }
    
    .attribution-text,
    .credit-text {
        text-align: center;
    }
    
    /* Sponsor Section Mobile */
    .sponsor-section {
        padding: 1.5rem 1rem;
        position: relative;
    position: relative;
  overflow-x: hidden; /* Add this line */
  background: var(--white);
  border-radius: 12px;
  padding: 2rem;
  margin: 2rem 0;
  text-align: center;
    }
    
    .sponsor-logos {
        padding: 2rem 1rem;
        min-height: 150px;
        font-size: 0.875rem;
    }

    /* How to Use Section Mobile */
    .how-to-use-section {
        padding: 1.5rem 1rem;
    }
    
    .how-to-use-item {
        font-size: 0.9rem;
        line-height: 1.5;
    }
    
    /* Coming Soon Mobile */
    .coming-soon {
        padding: 2rem 1rem;
    }
    
    /* Action Lists Mobile */
    .action-list {
        gap: 0.75rem;
    }
    
    .action-item {
        font-size: 0.9rem;
        line-height: 1.6;
    }
    
    /* CTA Section Mobile */
    .cta-section {
        padding: 1.5rem 1rem;
    }
    
    .cta-button {
        display: block;
        text-align: center;
        padding: 0.875rem;
        font-size: 0.875rem;
    }
    
    /* Q&A Section Mobile */
    .qa-item {
        margin-bottom: 1rem;
        padding-bottom: 1rem;
    }
    
    .qa-question {
        font-size: 0.9rem;
        line-height: 1.4;
    }
    
    .qa-answer {
        font-size: 0.9rem;
        line-height: 1.6;
        padding-left: 0.5rem;
    }
}

/* Small Mobile Styles */
@media (max-width: 480px) {
    
    
    .event-banner {
        padding: 1.5rem 0.75rem;
    }
    
    .event-banner h1 {
        font-size: 1.5rem;
    }
    
    .event-banner h1 span {
        font-size: 1.25rem;
    }
    
    .session-header,
    .video-section,
    .takeaways-section,
    .feedback-form,
    .rating-section,
    .attribution-section {
        padding: 0.75rem;
    }
    
    .breakthrough-item {
        padding: 0.75rem;
    }
    
    .section-box {
        padding: 0.75rem;
    }
    
    .breakthrough-title {
        font-size: 0.95rem;
    }
    
    .star {
        font-size: 1.5rem;
    }
    
    .content-tab {
        font-size: 0.8rem;
        padding: 0.625rem 0.75rem;
    }
}

/* Landscape Phone Orientation */
@media (max-height: 500px) and (orientation: landscape) {
    .mobile-header {
        height: 50px;
    }
    
    .main-content {
        padding-top: 50px;
    }
    
    .event-banner {
        padding: 1rem;
    }
    
    .video-container {
        padding-bottom: 40%;
    }
}

/* High DPI Displays */
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
    .star {
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
    }
}

/* Touch Device Optimizations */
@media (hover: none) and (pointer: coarse) {
    .nav-item {
        min-height: 44px; /* iOS touch target minimum */
    }
    
    .video-tab,
    .content-tab {
        min-height: 44px;
        display: flex;
        align-items: center;
        justify-content: center;
    }
    
    .speaker-toggle {
        min-height: 44px;
    }
    
    .star {
        min-width: 44px;
        min-height: 44px;
        display: flex;
        align-items: center;
        justify-content: center;
    }
    
    .feedback-submit,
    .cta-button,
    .back-button {
        min-height: 44px;
    }
}

/* Reduced Motion Preferences */
@media (prefers-reduced-motion: reduce) {
    * {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
    
    .sidebar,
    .mobile-overlay,
    .hamburger-line {
        transition: none;
    }
}

/* ================================================
   UNIVERSAL RESPONSIVE TYPOGRAPHY
   ================================================ */

/* Set a fluid base font size for the whole document */
body {
    font-size: clamp(1rem, 1vi + 0.5rem, 1.125rem);
    line-height: 1.6;
}

/* --- Headings --- */
.maintitle h1 {
    font-size: clamp(1.7rem, 3vi + 1rem, 2.6rem);
    line-height: 1.2;
}

h2, .how-to-use-title, .sponsor-title, .feedback-title, .rating-title {
    font-size: clamp(1.25rem, 4vi + 0.5rem, 1.75rem);
    line-height: 1.2;
}

h3 {
    font-size: clamp(1.1rem, 3vi + 0.5rem, 1.5rem);
    line-height: 1.3;
}

h4, .breakthrough-title {
    font-size: clamp(1rem, 2vi + 0.5rem, 1.2rem);
    line-height: 1.4;
}

/* --- Session-Specific Text --- */
.session-title {
    font-size: clamp(1.25rem, 5vi + 0.5rem, 1.8rem);
    line-height: 1.2;
}

.session-meta, .nav-text {
    font-size: clamp(0.8rem, 1vi + 0.5rem, 0.9rem);
    line-height: 1.4;
}

.breakthrough-text, .qa-answer, .big-picture-text, p {
    font-size: clamp(0.9rem, 2vi + 0.5rem, 1rem);
    line-height: 1.7;
}



/* ================================================
   SPONSOR CAROUSEL FOR MOBILE
   ================================================ */

/* Define the scrolling animation */
@keyframes scroll {
    0% {
        transform: translateX(0);
    }
    100% {
        /* Move the container left by the width of the original set of logos */
        transform: translateX(-50%);
    }
}

/* Hide the mobile carousel by default */
#sponsor-carousel-mobile {
    display: none;
}

@media (max-width: 768px) {

/* Hide the desktop logo container */
  .sponsor-logos {
    display: none;
  }

  /* Make the main section the positioning anchor for the fades */
  .sponsor-section {
    position: relative; 
  }

  /* Left fade effect, now attached to the stationary parent */
  .sponsor-section::before {
    content: '';
    position: absolute;
    left: 2rem;
    top: 0;
    bottom: 0;
    width: 50px;
    background: linear-gradient(to right, var(--white), transparent);
    z-index: 2;
    pointer-events: none;
  }
  
  /* Right fade effect, also attached to the stationary parent */
  .sponsor-section::after {
    content: '';
    position: absolute;
    right: 2rem;
    top: 0;
    bottom: 0;
    width: 50px;
    background: linear-gradient(to left, var(--white), transparent);
    z-index: 2;
    pointer-events: none;
  }

/* This new container will handle the scrolling and fades */
  .carousel-container {
    position: relative; /* Required for the fade elements */
    overflow-x: auto;   /* Enables horizontal scrolling */
will-change: scroll-position;
    -ms-overflow-style: none;  /* Hides scrollbar in IE and Edge */
    scrollbar-width: none;  /* Hides scrollbar in Firefox */
    -webkit-overflow-scrolling: touch; /* Smooth scrolling on iOS */
  }

  /* Hide the scrollbar in Chrome, Safari */
  .carousel-container::-webkit-scrollbar {
    display: none;
  }
  
  /* These create the fade effect on the left and right sides */
  .carousel-container::before,
  .carousel-container::after {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    width: 50px;
    z-index: 2; /* Places the fade on top of the logos */
    pointer-events: none; /* Allows scrolling through the fade */
  }

    /* On mobile, hide the original desktop grid */
    .sponsor-section .sponsor-logos {
        display: none;
    }

    /* Style and activate the mobile carousel */
    #sponsor-carousel-mobile {
        display: flex;
        flex-wrap: nowrap;
        width: fit-content; /* Make container width based on its content */
        align-items: center;
        gap: 0;
        padding: 1rem 0;
    }

    /* Prevent animation pause on hover for a continuous effect */
    #sponsor-carousel-mobile:hover {
        animation-play-state: running;
    }

    /* Style the individual logo links within the carousel */
    #sponsor-carousel-mobile .sponsor-logo-link {
        flex-shrink: 0;
        width: 200px; /* A consistent width for logos */
    }

    #sponsor-carousel-mobile .sponsor-logo-img {
        max-width: 100%;
        height: 80px;
        object-fit: contain;
    }
}

.page-content {
    display: block; /* Always take up space */
    opacity: 0;
    pointer-events: none;
    height: 0;
    overflow: hidden;
}

.page-content.active {
    opacity: 1;
    pointer-events: auto;
    height: auto;
    overflow: visible;
}


/* --- Toast Notification --- */
#toastNotification {
  visibility: hidden;
  padding: 1rem 1.5rem;
  position: fixed;
  z-index: 2000;
  left: 50%; /* Default centering */
  bottom: 30px;
  transform: translateX(-50%);
  border-radius: 8px;
  border: 1px solid transparent;
  font-size: 0.9rem; /* Reduced font size */
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  opacity: 0;
  transition: all 0.3s ease-in-out;
}

/* Modifier class for Success state */
#toastNotification.success {
  background-color: var(--toast-success-bg);
  border-color: var(--toast-success-border);
  color: var(--toast-success-text);
  text-align: center;
}

/* Modifier class for Error state */
#toastNotification.error {
  background-color: var(--toast-error-bg);
  border-color: var(--toast-error-border);
  color: var(--toast-error-text);
  text-align: center;
}

/* Class to show the toast */
#toastNotification.show {
  visibility: visible;
  opacity: 1;
  bottom: 50px;
}

/* Positioning for the toast on desktop screens */
@media (min-width: 769px) {
  /* Centred in the content column, not the viewport. */
  #toastNotification {
    /* (Viewport Width - Sidebar Width) / 2 + Sidebar Width */
    left: calc((100vw - var(--sidebar-rail)) / 2 + var(--sidebar-rail));
  }

  body.sidebar-is-expanded #toastNotification {
    left: calc((100vw - var(--sidebar-open)) / 2 + var(--sidebar-open));
  }
}

/* When a session has no preview clip the build adds .single-video, which drops
   the Preview tab and leaves the Full Session tab reading as a plain label. */
.video-tabs.single-video .video-tab:first-child {
    display: none;
}

/* ================================================
   TEMPLATE UTILITIES
   Classes that replace the per-element inline styles the legacy dashboards
   carried, so generated markup stays free of brand values.
   ================================================ */

/* The italic illustration paragraph inside a breakthrough item. */
.breakthrough-example {
    font-style: italic;
    margin: 1rem 0 1.5rem 1.5rem;
    color: var(--text-muted);
}

/* The legacy paragraph form of a Q&A pair ("qa.style": "paragraph"). The
   structured form uses .qa-item / .qa-question / .qa-answer further up, so this
   one carries its own class rather than redefining .qa-item and silently
   dropping that block's separator rule. */
.qa-item-plain {
    font-size: clamp(0.9rem, 2vi + 0.5rem, 1rem);
    line-height: 1.7;
    color: var(--text-body);
    margin-bottom: 1rem;
}

.qa-item-plain:last-child {
    margin-bottom: 0;
}

/* Last pair in a structured Q&A box: drop the trailing separator. */
.qa-item:last-child {
    margin-bottom: 0;
    padding-bottom: 0;
    border-bottom: none;
}

/* Links sitting on the dark attribution panel. */
.attribution-description a {
    color: var(--white);
}

.attribution-description a.underlined {
    text-decoration: underline;
}

/* Favicon chip in the mobile header. */
.mobile-logo img {
    border: 1px solid var(--medium-gray);
    border-radius: 4px;
}

/* Hero image on the intro page: letterbox against the brand dark. */
.hero-banner img {
    background-color: var(--brand-dark);
}

/* Agency credit block in the sidebar footer. */
.we-goliath-icon img {
    border-radius: 4px;
}

/* ================================================
   THUMBNAIL-GRID INTRO
   ================================================
   Renders only for `event.intro.layout: "thumbnail-grid"` - a title, one line of
   orientation copy, then the session cards. Nothing here is reachable from the
   default "panels" layout, so the two cannot interfere.

   The card is a <button> carrying data-session, which is the SAME contract a
   sidebar row uses; app.js's delegated handler matches `.nav-item, .session-card`
   and needs no card-specific code. Never make the card an <a href="#...">: the
   dashboard is one page and a hash would push history entries the back button
   then walks through one session at a time.
   ================================================ */

/* The white box: heading, blurb and cards in ONE container. Deliberately not
   `.session-header` — that class is a flex row built for a session page's title
   block, and the motion layer hangs a gold sweep off its ::after, which shows up
   under this panel as a stray fading line. */
.sessions-panel {
    background: var(--white);
    border-radius: 12px;
    padding: 1.75rem;
    margin-bottom: 2rem;
    box-shadow: var(--shadow-sm);
}

.sessions-panel-head {
    text-align: center;
}

/* Smaller than `.maintitle h1`'s 2.5rem, which read as shouting on a page whose
   real content is the cards. Sits just under a session page's own 1.8rem title:
   this is a label for the grid, not the loudest thing on the page. */
.sessions-panel-title {
    font-size: clamp(1.35rem, 1.2vi + 0.95rem, 1.7rem);
    font-weight: 700;
    line-height: 1.2;
    color: var(--text-primary);
    margin: 0;
}

.intro-blurb {
    max-width: 46rem;
    margin: 0.6rem auto 0;
    font-size: clamp(0.92rem, 2vi + 0.45rem, 1rem);
    line-height: 1.65;
    color: var(--text-secondary);
}

/* Three columns is the brief, not a consequence of the card width: nine sessions
   read as three rows of three. auto-fit would reflow to 4-up on a wide screen and
   lose that. The step-downs below are the only places the count changes. */
.session-card-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1.5rem;
    /* Top margin only: the panel's own padding closes the bottom, so a margin
       here would double it. */
    margin: 1.75rem 0 0;
}

/* A single tile left over in the last row (ten sessions in a three-up grid) would
   sit at the left; drop it into the centre column so the row reads as centred.
   Three-column layout only - the max-width blocks below reset it, or a one-column
   grid would fling this card into a phantom second column. */
.session-card-grid > .session-card:last-child:nth-child(3n + 1) {
    grid-column: 2;
}

.session-card {
    display: block;
    width: 100%;
    padding: 0;
    border: none;
    border-radius: var(--border-radius);
    background: var(--brand-dark);
    cursor: pointer;
    box-shadow: var(--shadow-sm);
    /* Inherit the page's type: a <button> otherwise falls back to the UA's
       13px system face, which the fallback tile and the veil would render in. */
    font-family: inherit;
    color: var(--white);
    text-align: left;
    transition: transform 0.25s ease, box-shadow 0.25s ease;
}

/* The clipping layer. `overflow: hidden` lives here rather than on the button so
   the button itself can carry the lift and the ring without clipping its own
   shadow, and so the image can scale inside a box that does not move. */
.session-card-frame {
    position: relative;
    display: block;
    border-radius: inherit;
    overflow: hidden;
    /* Makes the frame a query container, so the veil's type and padding scale
       with the CARD rather than the window. A viewport-based clamp looked right
       at every breakpoint and clipped badly BETWEEN them: at 1180px the window is
       wide (so the type stayed large) while the three-up card had shrunk to
       329px, and the description lost its first line. Card width is the only
       thing the copy actually has to fit. */
    container-type: inline-size;
}

.session-card-img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    transition: transform 0.45s ease;
}

.session-card:hover,
.session-card.is-peeking,
.session-card:focus-visible {
    transform: translateY(-4px);
    box-shadow: var(--shadow-lg);
}

.session-card:hover .session-card-img,
.session-card.is-peeking .session-card-img,
.session-card:focus-visible .session-card-img {
    transform: scale(1.045);
}

/* The gold edge is an inset shadow on its own layer, not a border and not a
   shadow on the frame itself. A border would change the card's box and shift
   every tile in the row by a pixel on hover; an inset shadow ON the frame paints
   beneath the frame's children, so the veil covered it and the ring never
   appeared on a card that had a description. */
.session-card-frame::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    box-shadow: inset 0 0 0 2px var(--brand-secondary);
    opacity: 0;
    transition: opacity 0.25s ease;
    pointer-events: none;
    z-index: 2;
}

.session-card:hover .session-card-frame::after,
.session-card.is-peeking .session-card-frame::after,
.session-card:focus-visible .session-card-frame::after {
    opacity: 1;
}

.session-card:focus-visible {
    outline: 3px solid var(--brand-secondary);
    outline-offset: 3px;
}

/* ---- the veil: session description on hover / first tap ----
   Sits over the card and rises into place. Opacity AND translate, so it reads as
   arriving rather than blinking. `pointer-events: none` matters: the veil covers
   the whole card, and without it the second tap on a touch screen would land on
   the veil instead of the button and never navigate. */
.session-card-veil {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    gap: 0.4rem;
    /* Every size below is in cqw - a percentage of the CARD's width - with a plain
       rem fallback first for browsers without container queries (the invalid
       clamp is then simply ignored).

       Kept tight on purpose. A card is only ~200px tall at three-up, and
       `justify-content: flex-end` pushes any overflow UP and out of the box -
       where `scrollHeight` cannot see it, so an over-long description clips its
       own first line and nothing reports it. Measure the first child's top edge
       against the veil's content box, at many widths, when changing this or the
       copy: scratchpad/check_veil_fit.py sweeps 25 of them. */
    padding: 1rem;
    padding: clamp(0.6rem, 3.4cqw, 1.15rem);
    /* Nearly flat, not a bottom-anchored scrim. The description fills most of the
       card, so a gradient that faded out by 78% left the artwork's own title and
       SPEAKERS list ghosting through the copy. The blur keeps a suggestion of the
       card underneath without competing; browsers without it just get the tint. */
    background: linear-gradient(
        to top,
        rgba(var(--brand-dark-rgb), 0.96) 0%,
        rgba(var(--brand-dark-rgb), 0.94) 70%,
        rgba(var(--brand-dark-rgb), 0.88) 100%
    );
    backdrop-filter: blur(2px);
    opacity: 0;
    transform: translateY(10px);
    transition: opacity 0.25s ease, transform 0.25s ease;
    pointer-events: none;
}

.session-card:hover .session-card-veil,
.session-card.is-peeking .session-card-veil,
.session-card:focus-visible .session-card-veil {
    opacity: 1;
    transform: none;
}

.session-card-when {
    font-size: 0.68rem;
    font-size: clamp(0.6rem, 2.1cqw, 0.72rem);
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--brand-secondary);
}

.session-card-desc {
    font-size: 0.86rem;
    font-size: clamp(0.7rem, 2.9cqw, 0.95rem);
    line-height: 1.5;
    color: var(--white);
}

/* intro.card_show_meta = false. With the time line gone the veil has the top
   of the card back, so the description takes it and typesets larger. Scoped to
   the modifier so a grid that keeps its times stays on the proven size that the
   veil-fit sweep validated. Re-run scratchpad/check_veil_fit.py after touching
   this - the description still has to clear the card at every width. */
.session-card-veil--roomy .session-card-desc {
    font-size: 0.98rem;
    font-size: clamp(0.8rem, 3.5cqw, 1.12rem);
    line-height: 1.55;
}

.session-card-cue {
    font-size: 0.72rem;
    font-size: clamp(0.6rem, 2.1cqw, 0.74rem);
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--brand-secondary);
}

.session-card-cue::after {
    content: " \2192";
}

/* A session with no `thumbnail`. Same footprint as an image card so one missing
   file does not break the row rhythm. schema.py warns when this branch is live. */
.session-card-fallback {
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    aspect-ratio: 16 / 9;
    padding: 1.25rem;
    font-family: var(--font-heading);
    font-size: clamp(1rem, 2vi + 0.6rem, 1.35rem);
    line-height: 1.3;
    color: var(--brand-secondary);
    background: linear-gradient(135deg, var(--brand-dark) 0%, var(--brand-primary) 100%);
}

.session-card-eyebrow {
    display: block;
    margin-bottom: 0.5rem;
    font-family: var(--font-body);
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--white);
}

@media (max-width: 1024px) {
    .session-card-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    /* Below three columns the lone-tile centring no longer applies - let it flow. */
    .session-card-grid > .session-card:last-child:nth-child(3n + 1) {
        grid-column: auto;
    }
}

@media (max-width: 600px) {
    .session-card-grid {
        grid-template-columns: minmax(0, 1fr);
        gap: 1rem;
        margin-top: 1.25rem;
    }

    .sessions-panel {
        padding: 1.15rem;
    }
}

/* ================================================
   MOTION AND ACCENT LAYER
   ================================================
   Standard on every dashboard. Built as a FlexFest variant first and promoted
   here once it held up, so it is written to work for any brand: no colour
   appears below that is not already a token, and the whole layer resolves in
   --brand-primary, --brand-secondary and --brand-dark.

   It lives at the END of this file on purpose. Two rules override earlier
   declarations at equal specificity and win on source order, which is what lets
   this section carry no `!important` at all - it needed several while it was
   riding in brand.json's custom_css, because that lands in theme.css and
   theme.css loads first.

   Switch it off for an event with `"motion": "none"` in brand.json.
   ================================================ */

/* ---- Session pages arrive rather than appear ----
   Opening a session is the one interaction every reader performs, so that is
   where the motion belongs. app.js toggles .page-content.active, which restarts
   these on each visit.

   fill-mode is `backwards`, NOT `both`, and the distinction is load-bearing:
   `both` keeps the animation's end value (transform: none) applying after it
   finishes, and a filled animation outranks a normal declaration in the cascade,
   which silently disables the hover lift further down. */
@keyframes ff-rise {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: none; }
}

.page-content.active .big-picture-section,
.page-content.active .breakthrough-item,
.page-content.active .section-box,
.page-content.active .cta-section {
    animation: ff-rise 0.5s cubic-bezier(0.22, 0.61, 0.36, 1) backwards;
}

/* A short stagger over the first few, then flat. Uncapped, a 20-breakthrough
   session would still be sliding in a second and a half after it opened. */
.page-content.active .breakthrough-item:nth-of-type(1) { animation-delay: 0.05s; }
.page-content.active .breakthrough-item:nth-of-type(2) { animation-delay: 0.10s; }
.page-content.active .breakthrough-item:nth-of-type(3) { animation-delay: 0.15s; }
.page-content.active .breakthrough-item:nth-of-type(4) { animation-delay: 0.20s; }
.page-content.active .breakthrough-item:nth-of-type(n+5) { animation-delay: 0.24s; }

/* ---- Thumbnail cards arrive in sequence ----
   Same rise, walked across the grid so the three rows resolve one after another
   instead of appearing as a block. `backwards` and NOT `forwards`/`both` is
   load-bearing: a filled animation on `transform` would outrank the hover lift
   for the rest of the session, and the card would stop responding to the pointer
   while still looking perfectly fine in a screenshot. */
.page-content.active .session-card {
    animation: ff-rise 0.5s cubic-bezier(0.22, 0.61, 0.36, 1) backwards;
}

.page-content.active .session-card:nth-of-type(1) { animation-delay: 0.04s; }
.page-content.active .session-card:nth-of-type(2) { animation-delay: 0.08s; }
.page-content.active .session-card:nth-of-type(3) { animation-delay: 0.12s; }
.page-content.active .session-card:nth-of-type(4) { animation-delay: 0.16s; }
.page-content.active .session-card:nth-of-type(5) { animation-delay: 0.20s; }
.page-content.active .session-card:nth-of-type(6) { animation-delay: 0.24s; }
.page-content.active .session-card:nth-of-type(n+7) { animation-delay: 0.28s; }

/* ---- Breakthrough cards answer the pointer ----
   These are the most repeated element on a dashboard and were flat white with a
   hairline border. A lift, plus an accent edge that draws itself downward. */
.breakthrough-item {
    position: relative;
    overflow: hidden;
    transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
}

.breakthrough-item::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: linear-gradient(180deg, var(--brand-secondary), var(--brand-primary));
    transform: scaleY(0);
    transform-origin: top;
    transition: transform 0.3s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.breakthrough-item:hover::before,
.breakthrough-item:focus-within::before {
    transform: scaleY(1);
}

.breakthrough-item:hover,
.breakthrough-item:focus-within {
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
    border-color: rgba(var(--brand-primary-rgb), 0.35);
}

/* ---- Section accent bars draw themselves ----
   .section-box-title::before already exists further up; this adds only the
   animation, so the bar itself is untouched. */
@keyframes ff-grow {
    from { transform: scaleY(0); }
    to   { transform: scaleY(1); }
}

.page-content.active .section-box-title::before {
    transform-origin: center;
    animation: ff-grow 0.45s 0.18s cubic-bezier(0.22, 0.61, 0.36, 1) backwards;
}

/* ---- A hover rail in the sidebar ----
   Height rather than width, so the rail can never nudge a label sideways. The
   selected and Home rows are left alone: they are already filled. */
.nav-item::after {
    content: '';
    position: absolute;
    left: 0;
    top: 50%;
    width: 3px;
    height: 0;
    transform: translateY(-50%);
    background: var(--brand-secondary);
    border-radius: 0 2px 2px 0;
    transition: height 0.25s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.nav-item:hover::after {
    height: 58%;
}

.nav-item.active::after,
.nav-item.intro-item::after {
    height: 0;
}

/* ---- Quotes warm up under the pointer ----
   Tint and shadow only: thickening the 4px left border would reflow the text
   inside it, which is the kind of movement worth avoiding. */
.quote-box {
    transition: background 0.3s ease, box-shadow 0.25s ease;
}

.quote-box:hover {
    background: linear-gradient(135deg,
        rgba(var(--brand-primary-rgb), 0.10),
        rgba(var(--brand-secondary-rgb), 0.10));
    box-shadow: var(--shadow-sm);
}

/* ---- The analogy reads as its own beat ----
   An unlabelled indented paragraph under Key Insight had only italics holding it
   apart from the insight above. */
.breakthrough-content .breakthrough-example {
    border-left: 2px solid rgba(var(--brand-secondary-rgb), 0.85);
    padding-left: 1rem;
    margin-left: 0.5rem;
}

/* ---- The Core Question picks up the tint the rest of the page uses ----
   It was flat grey while the quote boxes, the big-picture panel and the CTA all
   carried the primary-to-secondary wash. */
.breakthrough-content .core-question-box {
    background: linear-gradient(135deg,
        rgba(var(--brand-primary-rgb), 0.07),
        rgba(var(--brand-secondary-rgb), 0.07));
}

/* ---- Reflection prompts lean in ---- */
.action-item,
.action-item::before {
    transition: transform 0.2s ease;
}

.action-item:hover::before {
    transform: translateX(3px);
}

/* ---- A wash behind the content column ----
   Two very low-alpha gradients. Because a scroll container paints its own
   background against its border box, these stay put while the content moves over
   them, which is what makes it read as depth rather than as a coloured block. */
.main-content {
    background:
        radial-gradient(900px 420px at 100% 0%,
            rgba(var(--brand-secondary-rgb), 0.11), transparent 62%),
        radial-gradient(760px 400px at 0% 10%,
            rgba(var(--brand-primary-rgb), 0.07), transparent 58%);
}

/* ---- A thin accent underline on each session header ---- */
@keyframes ff-sweep {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
}

.session-header {
    position: relative;
}

.session-header::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 2px;
    background: linear-gradient(90deg,
        var(--brand-secondary),
        rgba(var(--brand-secondary-rgb), 0) 70%);
    transform-origin: left;
}

.page-content.active .session-header::after {
    animation: ff-sweep 0.7s 0.1s cubic-bezier(0.22, 0.61, 0.36, 1) backwards;
}

/* ---- Larger tap targets for the hover-driven bits on touch ---- */
@media (max-width: 768px) {
    /* A pointer that cannot hover gets no lift, so the card keeps its resting
       shadow rather than flashing one on tap. */
    .breakthrough-item:hover,
    .breakthrough-item:focus-within {
        transform: none;
    }
}

/* ---- Honour a reduced-motion preference ----
   Not optional, and not redundant: the template's global rule further up only
   shortens animations to 0.01ms, which leaves animation-name and its fill still
   applying. These switch them off outright, so everything resolves to its
   finished state and the page is complete and static rather than half-animated. */
@media (prefers-reduced-motion: reduce) {
    .page-content.active .big-picture-section,
    .page-content.active .breakthrough-item,
    .page-content.active .section-box,
    .page-content.active .cta-section,
    .page-content.active .section-box-title::before,
    .page-content.active .session-header::after,
    .page-content.active .session-card {
        animation: none;
        opacity: 1;
        transform: none;
    }

    .breakthrough-item,
    .breakthrough-item::before,
    .quote-box,
    .nav-item::after,
    .action-item,
    .action-item::before,
    .session-card,
    .session-card-img,
    .session-card-veil,
    .session-card-frame::after {
        transition: none;
    }

    .breakthrough-item:hover,
    .breakthrough-item:focus-within {
        transform: none;
    }

    /* The veil still appears and the ring still lands - they carry information.
       Only the movement goes: no lift, no image zoom, no slide. */
    .session-card:hover,
    .session-card.is-peeking,
    .session-card:focus-visible {
        transform: none;
    }

    .session-card:hover .session-card-img,
    .session-card.is-peeking .session-card-img,
    .session-card:focus-visible .session-card-img {
        transform: none;
    }
}

/* ---- chatbot launcher ---------------------------------------------------
   The vendor embed (Lovable's embed.js) only pins an always-open iframe with no
   close control, so the dashboard owns the open/close button and the panel
   chrome, and lazy-loads the bot's /embed page into the frame on first open. */
.chatbot-launcher {
    position: fixed;
    right: 20px;
    bottom: 20px;
    z-index: 2147483000;
}
.chatbot-toggle {
    width: 60px;
    height: 60px;
    border-radius: 50%;
    border: none;
    background: var(--brand-dark);
    color: var(--white);
    cursor: pointer;
    display: grid;
    place-items: center;
    box-shadow: 0 12px 30px -8px rgba(var(--brand-dark-rgb), 0.55);
    transition: transform 0.15s ease, box-shadow 0.15s ease;
    margin-left: auto;
}
.chatbot-toggle:hover {
    transform: translateY(-2px);
    box-shadow: 0 16px 34px -8px rgba(var(--brand-dark-rgb), 0.62);
}
.chatbot-toggle:focus-visible {
    outline: 3px solid var(--brand-secondary);
    outline-offset: 2px;
}
.chatbot-icon-close { display: none; }
.chatbot-launcher.is-open .chatbot-icon-open { display: none; }
.chatbot-launcher.is-open .chatbot-icon-close { display: block; }

.chatbot-panel {
    position: absolute;
    right: 0;
    bottom: 76px;
    width: min(400px, calc(100vw - 40px));
    height: min(600px, calc(100vh - 120px));
    border-radius: 16px;
    overflow: hidden;
    background: var(--white);
    box-shadow: 0 24px 60px -18px rgba(20, 25, 40, 0.35);
}
.chatbot-panel[hidden] { display: none; }
.chatbot-frame {
    width: 100%;
    height: 100%;
    border: 0;
    display: block;
}

@media (max-width: 600px) {
    .chatbot-launcher { right: 14px; bottom: 14px; }
    .chatbot-panel { bottom: 70px; height: min(72vh, calc(100vh - 92px)); }
}
@media (prefers-reduced-motion: reduce) {
    .chatbot-toggle { transition: none; }
    .chatbot-toggle:hover { transform: none; }
}
