/* ============================================
   Hollis Artspace - Main Stylesheet
   Art gallery aesthetic with warm, inviting tones
   Mobile-first responsive design
   ============================================ */

/* --- CSS Variables --- */
:root {
    --color-primary: #2C3E50;
    --color-primary-dark: #1A2A3A;
    --color-primary-darker: #0F1C29;
    /* Button fill, derived from the logo rather than the slate. See the
       comment above .btn-primary. */
    --color-button: #316394;
    --color-button-hover: #2A547E;
    --color-accent: #C0785C;
    --color-accent-hover: #A8654A;
    --color-sage: #A8B5A2;
    --color-sage-light: #D4DDD0;
    --color-bg: #FAF8F5;
    --color-bg-warm: #F5F0EB;
    --color-text: #2D2D2D;
    --color-text-light: #5A5A5A;
    --color-white: #FFFFFF;
    --color-dark: #1A1A2E;
    --color-border: #E8E2DC;
    --font-heading: 'Playfair Display', Georgia, serif;
    --font-body: 'Source Sans 3', 'Source Sans Pro', -apple-system, BlinkMacSystemFont, sans-serif;
    --max-width: 1200px;
    --header-height: 80px;
    --transition: 0.3s ease;
    --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.08);
    --shadow-md: 0 4px 20px rgba(0, 0, 0, 0.1);
    --shadow-lg: 0 8px 40px rgba(0, 0, 0, 0.15);
    --radius: 8px;
    --radius-lg: 12px;
}

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

html, body {
    overflow-x: hidden;
}

html {
    scroll-behavior: smooth;
    -webkit-text-size-adjust: 100%;
}

body {
    font-family: var(--font-body);
    font-size: 16px;
    line-height: 1.7;
    color: var(--color-text);
    background-color: var(--color-bg);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

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

a {
    color: var(--color-accent);
    text-decoration: none;
    transition: color var(--transition);
}

a:hover {
    color: var(--color-accent-hover);
}

h1, h2, h3, h4, h5, h6 {
    font-family: var(--font-heading);
    color: var(--color-primary);
    line-height: 1.3;
    font-weight: 700;
}

h1 { font-size: 2rem; margin-bottom: 1rem; }
h2 { font-size: 1.75rem; margin-bottom: 0.75rem; }
h3 { font-size: 1.35rem; margin-bottom: 0.5rem; }
h4 { font-size: 1.1rem; margin-bottom: 0.5rem; }

p { margin-bottom: 1rem; }

.container {
    max-width: var(--max-width);
    margin: 0 auto;
    padding: 0 20px;
}

/* --- Top Bar --- */
.top-bar {
    background-color: var(--color-primary);
    color: var(--color-white);
    font-size: 0.85rem;
    padding: 8px 0;
}

.top-bar-inner {
    max-width: var(--max-width);
    margin: 0 auto;
    padding: 0 20px;
    display: flex;
    justify-content: flex-end;
    align-items: center;
    flex-wrap: wrap;
    gap: 16px;
}

.top-bar span {
    opacity: 0.9;
}

.top-bar a {
    color: var(--color-white);
    font-weight: 600;
}

.top-bar a:hover {
    color: var(--color-accent);
}

.top-bar-social {
    display: flex;
    gap: 12px;
    align-items: center;
}

.top-bar-social a {
    display: flex;
    align-items: center;
    opacity: 0.9;
}

.top-bar-social a:hover {
    opacity: 1;
}

.top-bar-social svg {
    width: 18px;
    height: 18px;
}

/* --- Header --- */
.site-header {
    background: var(--color-white);
    position: sticky;
    top: 0;
    z-index: 1000;
    transition: box-shadow var(--transition);
    border-bottom: 1px solid var(--color-border);
}

.site-header.scrolled {
    box-shadow: var(--shadow-md);
}

.header-inner {
    max-width: var(--max-width);
    margin: 0 auto;
    padding: 0 20px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: var(--header-height);
}

.header-logo {
    display: flex;
    align-items: center;
    gap: 12px;
    text-decoration: none;
}

.header-logo img {
    height: 90px;
    width: auto;
    border-radius: 50%;
    position: relative;
    z-index: 10;
    margin-top: -25px;
    margin-bottom: -25px;
}

@media (min-width: 768px) {
    .header-logo img {
        height: 130px;
        margin-top: -40px;
        margin-bottom: -40px;
    }
}

.logo-text {
    display: flex;
    flex-direction: column;
    line-height: 1.2;
}

.logo-name {
    font-family: var(--font-heading);
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--color-primary);
}

.logo-tagline {
    font-size: 0.75rem;
    color: var(--color-accent);
    font-weight: 500;
    letter-spacing: 1px;
    text-transform: uppercase;
}

/* --- Mobile Menu Toggle --- */
.menu-toggle {
    display: flex;
    flex-direction: column;
    gap: 5px;
    background: none;
    border: none;
    cursor: pointer;
    padding: 8px;
    z-index: 1001;
}

.menu-toggle span {
    display: block;
    width: 26px;
    height: 2px;
    background: var(--color-primary);
    transition: var(--transition);
    border-radius: 2px;
}

/* --- Navigation --- */
.header-nav {
    display: none;
    position: fixed;
    top: 0;
    right: -100%;
    width: 85%;
    max-width: 380px;
    height: 100vh;
    background: var(--color-white);
    box-shadow: var(--shadow-lg);
    transition: right var(--transition);
    z-index: 1000;
    overflow-y: auto;
    padding: 80px 24px 24px;
}

.header-nav.active {
    display: block;
    right: 0;
}

.nav-menu {
    list-style: none;
    display: flex;
    flex-direction: column;
}

.nav-menu > li {
    border-bottom: 1px solid var(--color-border);
}

.nav-menu a {
    display: block;
    padding: 14px 0;
    color: var(--color-text);
    font-weight: 500;
    font-size: 1rem;
    white-space: nowrap;
}

.nav-menu a:hover,
.nav-menu a.active {
    color: var(--color-accent);
}

/* Dropdown */
.dropdown-toggle {
    display: inline-flex !important;
    align-items: center;
    gap: 2px;
}

.dropdown-arrow {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    transition: transform var(--transition);
}

.nav-dropdown {
    list-style: none;
    display: none;
    padding-left: 16px;
}

.dropdown-open .nav-dropdown {
    display: block;
}

.dropdown-open .dropdown-arrow {
    transform: rotate(180deg);
}

.nav-dropdown a {
    padding: 10px 0;
    font-size: 0.95rem;
    color: var(--color-text-light);
}

/* Header Actions */
.header-actions {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-top: 24px;
    padding-top: 24px;
    border-top: 1px solid var(--color-border);
}

.header-phone {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--color-primary);
    font-weight: 600;
    font-size: 1.05rem;
}

.header-phone svg {
    width: 20px;
    height: 20px;
}

.header-social {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--color-text-light);
}

.header-social svg {
    width: 22px;
    height: 22px;
}

.header-cta {
    display: inline-block;
    background: var(--color-primary);
    color: var(--color-white) !important;
    padding: 10px 24px;
    border-radius: var(--radius);
    font-weight: 600;
    text-align: center;
    transition: background var(--transition);
}

.header-cta:hover {
    background: var(--color-primary-dark);
}

/* --- Buttons --- */
.btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 12px 28px;
    border-radius: var(--radius);
    font-weight: 600;
    font-size: 1rem;
    text-decoration: none;
    transition: all var(--transition);
    cursor: pointer;
    border: 2px solid transparent;
    line-height: 1.4;
}

/* Buttons are blue, not the terracotta accent, at the owner's request. The
   one rule that matters: a button must never be blue on blue. The home hero
   sits on a blue overlay and the footer is near-black navy, so buttons there
   use .btn-white instead — see .site-footer .newsletter-btn below and the
   hero markup in index.html.

   .btn-primary is --color-button, keyed to the logo. #785 made it the near-
   black --color-primary-dark and the owner reported that as too dark (#827),
   asking for something a little darker than the logo. The logo's blue is
   #3870A8 — which the palette never matched, so this is a different hue from
   the slate, not a shade of it. --color-button is that blue at 88%: 6.3:1 on
   white, still clearly the heavier of the two buttons next to a slate
   .btn-secondary.

   It is deliberately its own token rather than a change to
   --color-primary-dark. That variable is also the darken-step for the five
   things whose base is --color-primary (.header-cta:hover,
   .btn-secondary:hover, .btn-submit:hover, .newsletter-btn:hover, and the
   dark end of the .section-cta-block gradient). Pointing it at a lighter,
   more saturated blue would make every one of those hovers lighten instead
   of darken, and invert the gradient. */
.btn-primary {
    background: var(--color-button);
    color: var(--color-white);
    border-color: var(--color-button);
}

.btn-primary:hover {
    background: var(--color-button-hover);
    border-color: var(--color-button-hover);
    color: var(--color-white);
}

.btn-secondary {
    background: var(--color-primary);
    color: var(--color-white);
    border-color: var(--color-primary);
}

.btn-secondary:hover {
    background: var(--color-primary-dark);
    border-color: var(--color-primary-dark);
    color: var(--color-white);
}

.btn-outline {
    background: transparent;
    color: var(--color-white);
    border-color: var(--color-white);
}

/* Outline button for LIGHT backgrounds. .btn-outline is white-on-white there,
   which is how the specialty pages' "Contact Us" button all but disappeared. */
.btn-outline-dark {
    background: transparent;
    color: var(--color-primary);
    border-color: var(--color-primary);
}

.btn-outline-dark:hover {
    background: var(--color-primary);
    color: var(--color-white);
    border-color: var(--color-primary);
}

.btn-outline:hover {
    background: var(--color-white);
    color: var(--color-primary);
}

.btn-outline-accent {
    background: transparent;
    color: var(--color-primary);
    border-color: var(--color-primary);
}

.btn-outline-accent:hover {
    background: var(--color-primary);
    color: var(--color-white);
}

.btn-white {
    background: var(--color-white);
    color: var(--color-primary);
    border-color: var(--color-white);
}

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

.btn-outline-white {
    background: transparent;
    color: var(--color-white);
    border-color: rgba(255, 255, 255, 0.6);
}

.btn-outline-white:hover {
    background: var(--color-white);
    color: var(--color-primary);
    border-color: var(--color-white);
}

.btn-phone svg {
    width: 18px;
    height: 18px;
}

.btn-submit {
    background: var(--color-primary);
    color: var(--color-white);
    border: none;
    padding: 14px 32px;
    font-size: 1rem;
    font-weight: 600;
    border-radius: var(--radius);
    cursor: pointer;
    width: 100%;
    transition: background var(--transition);
}

.btn-submit:hover {
    background: var(--color-primary-dark);
}

/* --- Hero Sections --- */
.hero {
    position: relative;
    min-height: 400px;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    background-size: cover;
    background-position: center;
    color: var(--color-white);
    padding: 60px 20px;
}

.hero-overlay {
    position: absolute;
    inset: 0;
    background: linear-gradient(
        180deg,
        rgba(66, 115, 165, 0.55) 0%,
        rgba(44, 88, 136, 0.72) 100%
    );
}

.hero-home .hero-overlay {
    background: linear-gradient(
        180deg,
        rgba(78, 139, 193, 0.45) 0%,
        rgba(52, 103, 160, 0.68) 100%
    );
}

.hero-content {
    position: relative;
    z-index: 1;
    max-width: 700px;
}

.hero-tagline {
    font-family: var(--font-heading);
    font-size: 1rem;
    font-style: italic;
    color: var(--color-sage-light);
    margin-bottom: 12px;
}

/* White-on-photograph, and the sizes here have been round-tripped once — do
   not adjust either half without reading both.

   Legibility: the owner reported the hero as hard to read, so the heading
   carries Playfair's 800 weight (added to the font request in base.html) and
   both heading and subtitle carry a shadow — the overlay alone does not
   guarantee contrast, because the photograph behind it has light patches.
   The subtitle runs at full opacity for the same reason. Keep all of this.

   Size: #785 also scaled the type up, and the owner asked for that part back
   (#825) — she wanted it legible, not larger. So the sizes below and at the
   768px/1024px breakpoints are the pre-#785 values while the weight and
   shadow stay. Making it bigger again re-opens a complaint she has already
   made twice. */
.hero h1 {
    font-size: 2.2rem;
    font-weight: 800;
    color: var(--color-white);
    margin-bottom: 16px;
    line-height: 1.2;
    text-shadow: 0 2px 12px rgba(0, 0, 0, 0.45);
}

.hero-subtitle {
    font-size: 1.05rem;
    line-height: 1.6;
    opacity: 1;
    margin-bottom: 24px;
    text-shadow: 0 1px 8px rgba(0, 0, 0, 0.4);
}

.hero-buttons {
    display: flex;
    flex-direction: column;
    gap: 12px;
    align-items: center;
}

.visit-hours-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 24px;
    max-width: 720px;
    margin: 0 auto;
}

@media (min-width: 600px) {
    .visit-hours-grid {
        grid-template-columns: 1fr 1fr;
    }
}

.visit-hours-card {
    background: var(--color-white);
    border-radius: 12px;
    padding: 28px 24px;
    text-align: center;
    box-shadow: var(--shadow-sm);
}

.visit-hours-icon {
    width: 32px;
    height: 32px;
    color: var(--color-accent);
    margin-bottom: 8px;
}

.visit-hours-card h3 {
    font-family: var(--font-heading);
    font-size: 1.25rem;
    margin-bottom: 10px;
    color: var(--color-primary);
}

.visit-hours-lines {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 0.95rem;
    color: var(--color-text);
}

.visit-hours-line strong {
    color: var(--color-primary);
    margin-right: 6px;
}

.hero-page {
    min-height: 280px;
}

.hero-short {
    min-height: 180px;
    padding: 40px 0;
}

.hero-short h1 {
    font-size: 1.8rem;
    margin-bottom: 8px;
}

.hero-short p {
    font-size: 1rem;
    margin-bottom: 0;
}

.hero-page h1 {
    font-size: 2rem;
}

/* --- Sections --- */
.section {
    padding: 48px 0;
}

.section-light {
    background: var(--color-bg-warm);
}

.section-dark {
    background: var(--color-primary);
    color: var(--color-white);
}

.section-dark h2,
.section-dark h3 {
    color: var(--color-white);
}

.section-accent {
    background: var(--color-accent);
    color: var(--color-white);
}

.section-accent h2 {
    color: var(--color-white);
}

.section-sage {
    background: var(--color-sage-light);
}

.section-header {
    text-align: center;
    margin-bottom: 40px;
}

.section-header p {
    color: var(--color-text-light);
    max-width: 600px;
    margin: 0 auto;
    font-size: 1.05rem;
}

.section-cta {
    text-align: center;
    margin-top: 32px;
}

/* --- Class Category Cards --- */
.category-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 20px;
    justify-content: center;
}

.category-card {
    display: block;
    background: var(--color-white);
    border-radius: var(--radius-lg);
    overflow: hidden;
    text-decoration: none;
    box-shadow: var(--shadow-sm);
    transition: transform var(--transition), box-shadow var(--transition);
}

.category-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-md);
}

.category-card-image {
    height: 200px;
    overflow: hidden;
}

.category-card-image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform var(--transition);
}

.category-card:hover .category-card-image img {
    transform: scale(1.05);
}

.category-card-body {
    padding: 20px;
}

.category-card-body h3 {
    margin-bottom: 8px;
}

.category-card-body p {
    color: var(--color-text-light);
    font-size: 0.95rem;
    margin-bottom: 12px;
}

.category-card-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--color-accent);
    font-weight: 600;
    font-size: 0.9rem;
}

.category-card-link svg {
    width: 18px;
    height: 18px;
    transition: transform var(--transition);
}

.category-card:hover .category-card-link svg {
    transform: translateX(4px);
}

/* --- About Preview --- */
.about-preview {
    display: flex;
    flex-direction: column;
    gap: 32px;
    align-items: center;
}

.about-preview-image {
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-md);
    max-width: 400px;
}

.about-preview-image img {
    width: 100%;
    height: auto;
}

.about-preview-text h2 {
    margin-bottom: 16px;
}

.about-preview-text p {
    color: var(--color-text-light);
    margin-bottom: 16px;
}

/* --- Gallery Preview --- */
.gallery-preview-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
}

.gallery-preview-item {
    border-radius: var(--radius);
    overflow: hidden;
    aspect-ratio: 1;
    cursor: pointer;
}

.gallery-preview-item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform var(--transition);
}

.gallery-preview-item:hover img {
    transform: scale(1.05);
}

/* --- Gallery Page --- */
.gallery-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
}

.gallery-item {
    border-radius: var(--radius);
    overflow: hidden;
    cursor: pointer;
    aspect-ratio: 1;
    background: var(--color-border);
}

.gallery-item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform var(--transition), opacity var(--transition);
}

.gallery-item:hover img {
    transform: scale(1.05);
    opacity: 0.9;
}

/* --- Gallery Lightbox --- */
.gallery-lightbox {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.92);
    z-index: 9999;
    align-items: center;
    justify-content: center;
    padding: 20px;
}

.gallery-lightbox.active {
    display: flex;
}

.gallery-lightbox img {
    max-width: 90vw;
    max-height: 85vh;
    object-fit: contain;
    border-radius: var(--radius);
}

.gallery-lightbox-close {
    position: absolute;
    top: 16px;
    right: 20px;
    background: none;
    border: none;
    color: var(--color-white);
    font-size: 2.5rem;
    cursor: pointer;
    line-height: 1;
    padding: 8px;
    opacity: 0.8;
    transition: opacity var(--transition);
}

.gallery-lightbox-close:hover {
    opacity: 1;
}

.gallery-lightbox-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    background: rgba(255, 255, 255, 0.15);
    border: none;
    color: var(--color-white);
    font-size: 2.5rem;
    cursor: pointer;
    padding: 8px 16px;
    border-radius: var(--radius);
    transition: background var(--transition);
}

.gallery-lightbox-nav:hover {
    background: rgba(255, 255, 255, 0.3);
}

.gallery-lightbox-prev {
    left: 12px;
}

.gallery-lightbox-next {
    right: 12px;
}

/* --- Artist Profile --- */
.artist-profile {
    display: flex;
    flex-direction: column;
    gap: 32px;
}

.artist-portrait {
    text-align: center;
}

.artist-portrait img {
    width: 250px;
    height: 250px;
    object-fit: cover;
    border-radius: 50%;
    margin: 0 auto;
    box-shadow: var(--shadow-md);
}

.artist-info h2 {
    margin-bottom: 16px;
}

.artist-info p {
    color: var(--color-text-light);
    margin-bottom: 12px;
}

.artist-achievements {
    list-style: none;
    margin: 20px 0;
}

.artist-achievements li {
    padding: 8px 0;
    padding-left: 24px;
    position: relative;
    color: var(--color-text-light);
}

.artist-achievements li::before {
    content: '';
    position: absolute;
    left: 0;
    top: 16px;
    width: 8px;
    height: 8px;
    background: var(--color-accent);
    border-radius: 50%;
}

.artist-gallery {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
    margin-top: 24px;
}

.artist-gallery img {
    border-radius: var(--radius);
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
}

/* --- HiSawyer Embed --- */
.hisawyer-container {
    background: var(--color-white);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
    padding: 0;
    /* Anchors the bottom fade below. */
    position: relative;
}

/* The listing stops at a hard card edge, and the owner reported visitors
   reading that as the end of the offerings rather than as a box to scroll.
   The fade is the half of the fix that cannot break: it is our own element
   over our own card, so it needs nothing from the cross-origin widget and
   behaves identically in every browser.

   Inset on the right by the scrollbar width so it never paints over the bar
   in .hisawyer-scroll. Containers with no scroller set that to 0. */
.hisawyer-container::after {
    content: '';
    position: absolute;
    left: 0;
    right: var(--hisawyer-bar-width, 0px);
    bottom: 0;
    height: 72px;
    background: linear-gradient(
        to bottom,
        rgba(255, 255, 255, 0) 0%,
        rgba(255, 255, 255, 0.85) 55%,
        var(--color-white) 100%
    );
    pointer-events: none;
}

/* The embed is cross-origin, so it cannot be auto-sized to its content — the
   height here is what the visitor gets. It used to be 100vh on mobile, which
   sounds generous but is not: HiSawyer spends its first ~200px on a log-in
   row, a schedule dropdown and a filter bar, so a phone showed about two
   listings and then the box ended. The owner reported visitors reading that
   as "there are only two classes" rather than scrolling on.

   One global height does not fit five pages: the adult catalog is by far the
   longest and was still being clipped at the old 1500px desktop value, taking
   the Adult Workshops section below it with it. So the height is a custom
   property with a sane default, and a page that needs more sets its own via
   a modifier class.

   Do not set these straight from a `scrollHeight` reading. Measured against
   the live widget in Aug 2026, the adult listing reported 4252px on a desktop
   viewport and 1882px at 540px wide — but a box sized to the larger number
   is mostly empty on the page, because the widget reserves height it does not
   fill. The owner rejected that on sight. The values below are what actually
   looks right in the browser; the readings are recorded only as an upper
   bound, not as a target.

   Those two readings are now known to be artefacts, not measurements — see
   the block beside .hisawyer-listing-adult-classes below, which explains what
   the widget was actually reporting and how to measure it properly. They are
   left here because the conclusion they led to still stands.

   Whatever is left over past the box is reachable through the "View the full
   schedule on Sawyer" link directly beneath it, so erring toward the smaller
   box costs a click rather than hiding a class outright. */
.hisawyer-container iframe {
    width: 100%;
    border: none;
    min-height: var(--hisawyer-height, 1800px);
    display: block;
}

@media (min-width: 768px) {
    .hisawyer-container iframe {
        min-height: var(--hisawyer-height-desktop, 1500px);
    }
}

/* The adult catalog is the long one. */
.hisawyer-container-tall {
    --hisawyer-height: 2400px;
    --hisawyer-height-desktop: 2000px;
}

/* --- The scrollbar we own --------------------------------------------------

   The widget's own scrollbar is unreachable. It is painted inside a
   cross-origin document, so no rule of ours and no value of `scrolling=`
   touches it, and on macOS it is an overlay bar that fades out while idle —
   which is precisely the "looks cut off" report.

   So the scrollbar is moved out to an element we control. The iframe is sized
   to the widget's whole document rather than to the visible box, which leaves
   it with nothing to scroll internally; .hisawyer-scroll is then the only
   thing scrolling, and its bar is ours to style and to keep painted.

   THE HEIGHTS BELOW ARE MEASURED, AND THE OBVIOUS WAY TO MEASURE THEM IS
   WRONG. Reading the widget's scrollHeight against the box it is already in
   returns the box: on a desktop viewport it stretches its document to fill
   whatever height the iframe is given. That is where the discredited 4252px
   reading in the note above came from, and sizing to it is what produced the
   over-tall, mostly-empty box the owner rejected on sight.

   Force the iframe to 9000px first, then take the bottom of the lowest node
   that owns a non-whitespace text node or is an image — wrappers inherit
   their children's textContent and just echo the document height. Measured
   that way in a headed browser, Sep 2026, the adult catalog really ends at
   2245px on a 1280px viewport and 4755px at 390px wide. The narrower one
   being the taller one is the sane result the old readings inverted.

   The values keep a little headroom over those so a couple of added classes
   do not immediately overflow. Both directions of being wrong are survivable,
   which is what makes a measurement with a shelf life acceptable here: too
   tall shows blank at the end of the scroll, too short hands the tail back to
   the widget's own internal scrolling, i.e. the behaviour this replaced.
   Re-measure as above and retune here; nothing else needs to change. */
/* Turning the scroller on is the presence of the inner element, not a second
   class beside it — one thing to remember instead of two that can disagree.
   The width is what the fade above insets itself by so it never paints over
   the bar. */
.hisawyer-container:has(.hisawyer-scroll) {
    --hisawyer-bar-width: 12px;
}

/* Per-listing content heights, measured as described above in a headed
   browser, Sep 2026. `test_the_configured_heights_still_match_the_listings`
   re-measures these and fails when a listing has drifted; run it after Anna
   adds or retires a run of classes.

       listing                              phone (390)   desktop (1280)
       widget_tags=youth                       5085            2400
       widget_tags=mixed+ages                  4755            2245
       schedule_id=camps                       8953            4155
       schedule_id=camps&widget_tags=mixed…   10053            4149

   Resist merging the last two. They are the same schedule and they measured
   6px apart on desktop, so sharing one class looks obviously right — that is
   exactly what was tried, and the phone figures are 1100px apart. Adding the
   mixed+ages tag makes that listing *taller* on a phone, which is
   counterintuitive enough that the drift test is what found it rather than
   review.

   Values carry ~2-4% headroom over the measurements so that adding a class
   or two does not immediately push a listing back to scrolling itself. */
.hisawyer-listing-adult-classes {
    --hisawyer-content-height: 4900px;
    --hisawyer-content-height-desktop: 2400px;
}

.hisawyer-listing-youth-classes {
    --hisawyer-content-height: 5300px;
    --hisawyer-content-height-desktop: 2550px;
}

.hisawyer-listing-camps {
    --hisawyer-content-height: 9200px;
    --hisawyer-content-height-desktop: 4300px;
}

.hisawyer-listing-camps-mixed-ages {
    --hisawyer-content-height: 10300px;
    --hisawyer-content-height-desktop: 4300px;
}

/* The nine specialty listings, same measurement method, Sep 2026. These vary
   far more than the class pages do — a 10x spread on desktop, from zentangle
   at 951px to acrylics at 4597px — which is why they get one class each
   rather than a shared value.

       specialty       phone   desktop        specialty     phone   desktop
       watercolor       9249     4565         zentangle      1756      951
       oil-painting     6162     3029         sewing         3617     1883
       acrylics         9329     4597         writing        2071     1137
       fiber-arts       7751     3833
       mixed-media      9417     4578
       drawing          6242     2978

   Two of them are shorter than the box they would sit in, and those also set
   --hisawyer-height so the box shrinks to the listing rather than trailing
   blank space under it: zentangle on both viewports, writing on desktop only
   (its phone listing runs past the 1800px box and does scroll). A box that
   fits its content needs no bar, and `auto` above gives it none. */
.hisawyer-listing-specialty-watercolor {
    --hisawyer-content-height: 9650px;
    --hisawyer-content-height-desktop: 4750px;
}

.hisawyer-listing-specialty-oil-painting {
    --hisawyer-content-height: 6450px;
    --hisawyer-content-height-desktop: 3200px;
}

.hisawyer-listing-specialty-acrylics {
    --hisawyer-content-height: 9750px;
    --hisawyer-content-height-desktop: 4800px;
}

.hisawyer-listing-specialty-fiber-arts {
    --hisawyer-content-height: 8100px;
    --hisawyer-content-height-desktop: 4000px;
}

.hisawyer-listing-specialty-mixed-media {
    --hisawyer-content-height: 9800px;
    --hisawyer-content-height-desktop: 4800px;
}

.hisawyer-listing-specialty-drawing {
    --hisawyer-content-height: 6500px;
    --hisawyer-content-height-desktop: 3100px;
}

.hisawyer-listing-specialty-sewing {
    --hisawyer-content-height: 3800px;
    --hisawyer-content-height-desktop: 1980px;
}

/* Shorter than the default box on both viewports — box shrinks to match. */
.hisawyer-listing-specialty-zentangle {
    --hisawyer-content-height: 1850px;
    --hisawyer-content-height-desktop: 1000px;
    --hisawyer-height: 1850px;
    --hisawyer-height-desktop: 1000px;
}

/* Scrolls on a phone, fits on desktop. */
.hisawyer-listing-specialty-writing {
    --hisawyer-content-height: 2200px;
    --hisawyer-content-height-desktop: 1200px;
    --hisawyer-height-desktop: 1200px;
}

.hisawyer-scroll {
    height: var(--hisawyer-height, 1800px);
    /* `auto`, not `scroll`, and the difference matters now that the specialty
       listings are in here. Two of them are shorter than the box they sit in
       — zentangle is 951px on a desktop viewport — and those get a box shrunk
       to fit instead, where `scroll` would paint an empty track beside content
       that has nowhere to go. `auto` gives a bar exactly when there is
       something to scroll.

       What `scroll` used to guarantee is now guaranteed by measurement
       instead: test_every_scroll_wrapper_has_something_to_scroll asserts the
       overflow exists on the listings that are meant to have it, and the
       drift test keeps the configured heights honest. */
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
}

/* Firefox, which has no ::-webkit-scrollbar equivalent.

   The @supports guard is load-bearing, not tidiness. Chrome implements
   `scrollbar-width` too, and setting it makes Chrome ignore every
   ::-webkit-scrollbar rule on the element — so declaring this unguarded
   silently reverts Chrome to the overlay bar that fades out, which is the
   whole thing being fixed. Measured in a headed browser: webkit rules alone
   give a 14px bar, the same rules plus a bare `scrollbar-width: thin` give
   0px, and this guarded form gives 14px again. */
@supports not selector(::-webkit-scrollbar) {
    .hisawyer-scroll {
        scrollbar-width: thin;
        scrollbar-color: var(--color-text-light) var(--color-border);
    }
}

.hisawyer-scroll iframe {
    /* Overrides the min-height on .hisawyer-container iframe, which would
       otherwise fight the content height set here. */
    min-height: 0;
    height: var(--hisawyer-content-height, 4900px);
}

@media (min-width: 768px) {
    .hisawyer-scroll {
        height: var(--hisawyer-height-desktop, 1500px);
    }

    .hisawyer-scroll iframe {
        height: var(--hisawyer-content-height-desktop, 2400px);
    }
}

/* Declaring these opts the element out of macOS overlay scrollbars in Chrome
   and Safari: the bar becomes a classic one that is always painted, which is
   the entire point of the exercise. */
.hisawyer-scroll::-webkit-scrollbar {
    width: var(--hisawyer-bar-width, 12px);
}

.hisawyer-scroll::-webkit-scrollbar-track {
    background: var(--color-border);
    border-radius: 6px;
}

.hisawyer-scroll::-webkit-scrollbar-thumb {
    background: var(--color-text-light);
    border-radius: 6px;
    border: 2px solid var(--color-border);
}

.hisawyer-scroll::-webkit-scrollbar-thumb:hover {
    background: var(--color-primary);
}

/* An always-available way out of the box, in case a listing still falls past
   the height above — no visitor should be unable to reach a class. */
.hisawyer-fallback {
    margin-top: 16px;
    text-align: center;
    font-size: 0.9375rem;
}

.hisawyer-fallback a {
    color: var(--color-text-light);
    text-decoration: underline;
}

.hisawyer-fallback a:hover {
    color: var(--color-accent);
}

.class-intro {
    margin-bottom: 32px;
}

.class-intro h2 {
    margin-bottom: 12px;
}

.class-intro p {
    color: var(--color-text-light);
    font-size: 1.05rem;
}

/* A second listing on the same page needs air above it, otherwise its heading
   reads as a caption on the box that just ended rather than as the start of a
   new section. */
.class-intro-secondary {
    margin-top: 56px;
}

/* --- Trust Bar --- */
.trust-bar {
    background: var(--color-white);
    padding: 24px 0;
    border-bottom: 1px solid var(--color-border);
}

.trust-items {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 16px;
}

.trust-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px;
}

.trust-item svg {
    width: 32px;
    height: 32px;
    color: var(--color-accent);
    flex-shrink: 0;
}

/* The location item is an <a> to Google Maps; keep it looking identical to
   its sibling items rather than a default blue underlined link. */
.trust-item-link {
    text-decoration: none;
    color: inherit;
    border-radius: 6px;
    transition: background-color 0.2s ease;
}

.trust-item-link:hover,
.trust-item-link:focus-visible {
    background-color: var(--color-bg-warm);
}

.trust-item strong {
    display: block;
    font-size: 0.9rem;
    color: var(--color-primary);
}

.trust-item span {
    font-size: 0.8rem;
    color: var(--color-text-light);
}

/* --- CTA Section --- */
.cta-section {
    text-align: center;
    padding: 48px 20px;
}

.cta-section h2 {
    color: var(--color-white);
    margin-bottom: 12px;
}

.cta-section p {
    color: rgba(255, 255, 255, 0.9);
    max-width: 500px;
    margin: 0 auto 24px;
}

.cta-buttons {
    display: flex;
    flex-direction: column;
    gap: 12px;
    align-items: center;
}

/* .cta-section paints its heading and body white for the dark CTA band. The
   specialty pages reuse the same block on a pale sage background, where white
   text was effectively invisible (reported by the site owner). Restore normal
   dark text there. */
.cta-section-light h2,
.cta-section-light .section-title {
    color: var(--color-primary);
}

.cta-section-light p,
.cta-section-light .section-subtitle {
    color: var(--color-text);
}

.section-cta-block {
    background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-dark) 100%);
    color: var(--color-white);
}

/* The /news/ CTA carries the subscribe form (#918), and this band starts at
   --color-primary -- which is exactly .newsletter-btn's own fill, so the
   button would be invisible against the top of its own panel. White, as
   .site-footer and .section-cta-narrow already do for the same reason.

   The input needs no override here: this band is dark, which is what the
   base .newsletter-input rule is written for. */
.section-cta-block .newsletter-btn {
    background: var(--color-white);
    color: var(--color-primary);
}

.section-cta-block .newsletter-btn:hover {
    background: var(--color-bg-warm);
    color: var(--color-primary-dark);
}

/* Newsletter block: a contained panel rather than a full-bleed band, so it
   reads as a card on the page instead of a second wall of dark the same
   weight as the closing "Ready to Make Art?" CTA. The gradient stops at a
   slate blue rather than the near-black --color-primary-dark used above. */
.section-cta-narrow {
    background: var(--color-bg);
}

.cta-panel {
    max-width: 760px;
    margin: 0 auto;
    border-radius: 12px;
    background: linear-gradient(135deg, var(--color-primary) 0%, #3E5871 100%);
    color: var(--color-white);
}

.cta-panel .cta-section {
    padding: 40px 24px;
}

/* Signup outcome, swapped in where the form was by HTMX. Both places this can
   land are dark — the near-black footer and the blue Stay-in-the-Loop panel —
   so the text is white either way rather than inheriting the body colour and
   disappearing. Success and error differ by the rule beside them, not by
   colour alone: the same message reads as either depending on the outcome. */
.newsletter-success,
.newsletter-error {
    color: var(--color-white);
    font-size: 0.95rem;
    line-height: 1.5;
    text-align: center;
    padding: 12px 16px;
    border-radius: 6px;
    max-width: 450px;
    margin: 0 auto;
}

.newsletter-success {
    background: rgba(255, 255, 255, 0.12);
    border-left: 3px solid var(--color-sage-light);
}

.newsletter-error {
    background: rgba(192, 120, 92, 0.22);
    border-left: 3px solid var(--color-accent);
}

.newsletter-success p,
.newsletter-error p {
    margin: 0;
}

/* The Stay-in-the-Loop panel carries the subscribe form on the home page, and
   the panel is a blue gradient — so .newsletter-btn's --color-primary fill is
   the blue-on-blue case the rule at the top of the buttons section warns
   about. White here, exactly as .site-footer .newsletter-btn does it for the
   navy footer. The input itself needs no override: it is already styled for a
   dark backdrop (white text, translucent white border) because the footer is
   the same situation. */
.section-cta-narrow .newsletter-btn {
    background: var(--color-white);
    color: var(--color-primary);
}

.section-cta-narrow .newsletter-btn:hover {
    background: var(--color-bg-warm);
    color: var(--color-primary-dark);
}

/* The form is wider than the button it replaced, and the badge overhangs the
   panel's top-right corner, so the panel needs a little more room than the
   40px it carried when this was a single centred button. */
.section-cta-narrow .newsletter-form {
    margin-top: 24px;
}

/* "Read our latest newsletter" badge (#829), floating on the corner of the
   Stay-in-the-Loop panel. Modelled on harborchurch's "Now Open" seal — same
   structure (inline SVG, text on a rotating textPath, a slow float) in this
   site's palette rather than the terracotta.

   White fill rather than --color-bg: the badge straddles the panel's corner,
   so it sits half on the blue gradient and half on the cream page behind it,
   and needs to read against both.

   Positioned against .cta-panel, which is the 760px card — not the full-width
   section — so the offsets stay put as the viewport changes. The panel has no
   overflow:hidden, which is what lets the badge overhang its rounded corner. */
.section-cta-narrow .cta-panel {
    position: relative;
}

.ha-newsletter-badge {
    position: absolute;
    top: -26px;
    right: -26px;
    z-index: 2;
    width: 140px;
    height: 140px;
    filter: drop-shadow(0 8px 20px rgba(26, 42, 58, 0.35));
    animation: ha-badge-float 6s ease-in-out infinite;
    transform: rotate(-8deg);
    text-decoration: none;
}

.ha-newsletter-badge:hover {
    filter: drop-shadow(0 12px 28px rgba(26, 42, 58, 0.5));
}

.ha-badge-svg {
    width: 100%;
    height: 100%;
    display: block;
    overflow: visible;
}

.ha-badge-rot {
    transform-origin: 100px 100px;
    animation: ha-badge-spin 26s linear infinite;
}

.ha-badge-arc-text {
    font-family: var(--font-body);
    font-size: 11px;
    letter-spacing: 1.5px;
    fill: var(--color-button);
}

.ha-badge-line {
    font-family: var(--font-heading);
    font-weight: 700;
    fill: var(--color-button);
    font-size: 16px;
    letter-spacing: 0.5px;
}

.ha-badge-star {
    font-size: 14px;
    fill: rgba(49, 99, 148, 0.7);
}

@keyframes ha-badge-spin {
    to { transform: rotate(360deg); }
}

@keyframes ha-badge-float {
    0%, 100% { transform: rotate(-8deg) translateY(0); }
    50% { transform: rotate(-8deg) translateY(-7px); }
}

@media (prefers-reduced-motion: reduce) {
    .ha-newsletter-badge { animation: none; }
    .ha-badge-rot { animation: none; }
}

/* Tuck the badge inside the panel until there is room to overhang it.

   The panel is min(760px, viewport - 40px) centred in the container, so its
   right edge sits at 20 + (container_inner + panel_width) / 2. A 26px
   overhang clears the viewport only from roughly 815px up — at 768px the
   badge runs about 6px past the edge, where an ancestor clips it rather than
   scrolling the page, so it goes half-missing with nothing to show why.
   Hence 899px and not the 768px breakpoint used elsewhere in this file.
   e2e/test_golive.py asserts both the no-scroll and the fully-visible half of
   that, at 390/768/1280. */
@media (max-width: 899px) {
    .ha-newsletter-badge {
        width: 108px;
        height: 108px;
        top: -54px;
        right: -4px;
    }

    /* Lift the heading clear of the badge. On a wide panel the badge sits
       beyond the end of a centred heading; on a phone the panel is barely
       wider than the heading itself, so the badge lands on top of it and
       "Stay in the Loop" loses its last word. Raising the badge alone is not
       enough — it only moves the collision up the heading — so the panel
       makes room as well. The space it moves into is empty page background,
       which is why the badge can go above the panel edge at all. */
    .section-cta-narrow .cta-panel--badged .cta-section {
        padding-top: 68px;
    }
    /* The viewBox scales with the badge, so the three centre lines shrink
       with it — at the desktop size they resolve to ~11px on a phone, which
       is the point where "READ OUR LATEST NEWSLETTER" stops being readable
       and becomes texture. Scaled up here to hold roughly the painted size
       they have on a wide screen. */
    .ha-badge-line { font-size: 19px; }
    .ha-badge-arc-text { font-size: 12px; }
}

/* --- Contact Page --- */
.contact-newsletter {
    margin-top: 40px;
    padding: 32px 24px;
    border: 1px solid var(--color-border);
    border-radius: 12px;
    background: var(--color-bg-warm);
    text-align: center;
}

.contact-newsletter h3 {
    margin-bottom: 8px;
}

.contact-newsletter p {
    color: var(--color-text-light);
    max-width: 480px;
    margin: 0 auto 20px;
}

.contact-newsletter .newsletter-form {
    max-width: 480px;
    margin: 0 auto;
}

/* .newsletter-input is written for a dark backdrop -- white text on 10% white
   -- which is right in the navy footer, where that form lives on every other
   page. This panel is cream (--color-bg-warm), so the same rule renders white
   on cream: 1.13:1, i.e. invisible (#920). Scoped variant here rather than a
   change to the base rule, following .section-cta-narrow .newsletter-btn
   above, which solves the mirror-image problem for the button.

   The button needs no variant: it is dark slate on cream already. */
.contact-newsletter .newsletter-input {
    background: var(--color-white);
    border: 1px solid var(--color-border);
    color: var(--color-text);
}

.contact-newsletter .newsletter-input::placeholder {
    color: var(--color-text-light);
}

.contact-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 40px;
}

.contact-info h2 {
    margin-bottom: 12px;
}

.contact-intro {
    color: var(--color-text-light);
    margin-bottom: 24px;
}

.contact-info-item {
    display: flex;
    gap: 16px;
    margin-bottom: 20px;
    align-items: flex-start;
}

.contact-info-icon {
    width: 40px;
    height: 40px;
    background: var(--color-sage-light);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.contact-info-icon svg {
    width: 20px;
    height: 20px;
    color: var(--color-primary);
}

.contact-info-text h4 {
    font-family: var(--font-body);
    font-weight: 600;
    margin-bottom: 2px;
}

.contact-info-text a {
    color: var(--color-accent);
    font-weight: 500;
}

.contact-info-text p {
    color: var(--color-text-light);
    margin-bottom: 0;
    font-size: 0.95rem;
}

/* --- Contact Form --- */
.contact-form {
    background: var(--color-white);
    padding: 28px 24px;
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}

.form-group {
    margin-bottom: 20px;
}

.form-group label {
    display: block;
    font-weight: 600;
    margin-bottom: 6px;
    font-size: 0.95rem;
    color: var(--color-primary);
}

.required {
    color: var(--color-accent);
}

.form-group input,
.form-group select,
.form-group textarea {
    width: 100%;
    padding: 12px 14px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    font-size: 1rem;
    font-family: var(--font-body);
    color: var(--color-text);
    background: var(--color-bg);
    transition: border-color var(--transition), box-shadow var(--transition);
}

.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
    outline: none;
    border-color: var(--color-accent);
    box-shadow: 0 0 0 3px rgba(192, 120, 92, 0.15);
}

.form-group textarea {
    resize: vertical;
    min-height: 120px;
}

.form-errors {
    background: #fef2f2;
    border: 1px solid #fecaca;
    border-radius: var(--radius);
    padding: 12px 16px;
    margin-bottom: 20px;
}

.form-errors .error {
    color: #dc2626;
    font-size: 0.9rem;
    margin-bottom: 4px;
}

.form-errors .error:last-child {
    margin-bottom: 0;
}

/* --- Contact Success --- */
.contact-success {
    text-align: center;
    padding: 40px 20px;
}

.success-icon {
    margin-bottom: 16px;
}

.success-icon svg {
    width: 64px;
    height: 64px;
    color: var(--color-sage);
}

.contact-success h3 {
    margin-bottom: 8px;
    font-size: 1.5rem;
}

.contact-success p {
    color: var(--color-text-light);
}

.success-submessage {
    font-size: 0.9rem;
    margin-top: 12px;
}

/* --- Footer --- */
.site-footer {
    background: var(--color-dark);
    color: rgba(255, 255, 255, 0.8);
    padding: 48px 0 0;
}

.footer-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 32px;
    padding-bottom: 32px;
}

.footer-section h4 {
    color: var(--color-white);
    font-family: var(--font-heading);
    font-size: 1.1rem;
    margin-bottom: 16px;
}

.footer-brand p {
    font-size: 0.95rem;
    line-height: 1.7;
    margin-bottom: 16px;
}

.footer-logo-block {
    margin-bottom: 16px;
}

.footer-logo-text .logo-name {
    color: var(--color-white);
}

.footer-logo-text .logo-tagline {
    color: var(--color-sage);
}

.footer-nav {
    list-style: none;
}

.footer-nav li {
    margin-bottom: 8px;
}

.footer-nav a {
    color: rgba(255, 255, 255, 0.7);
    font-size: 0.95rem;
    transition: color var(--transition);
}

.footer-nav a:hover {
    color: var(--color-accent);
}

.footer-contact-item {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    margin-bottom: 14px;
}

.footer-contact-item svg {
    width: 18px;
    height: 18px;
    color: var(--color-sage);
    flex-shrink: 0;
    margin-top: 3px;
}

.footer-contact-item a {
    color: rgba(255, 255, 255, 0.8);
}

.footer-contact-item a:hover {
    color: var(--color-accent);
}

.footer-hours {
    margin-top: 16px;
    font-size: 0.9rem;
}

.footer-hours strong {
    color: var(--color-white);
}

.footer-social {
    margin-top: 16px;
    display: flex;
    gap: 16px;
}

.footer-social a {
    display: flex;
    align-items: center;
    gap: 8px;
    color: rgba(255, 255, 255, 0.7);
    font-size: 0.9rem;
    transition: color var(--transition);
}

.footer-social a:hover {
    color: var(--color-accent);
}

.footer-social svg {
    width: 22px;
    height: 22px;
}

.footer-bottom {
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    padding: 20px 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
    align-items: center;
    text-align: center;
    font-size: 0.85rem;
}

.footer-bottom a {
    color: var(--color-sage);
}

.footer-bottom a:hover {
    color: var(--color-accent);
}

/* --- Mobile Call Button --- */
.mobile-call-btn {
    position: fixed;
    bottom: 20px;
    right: 20px;
    width: 56px;
    height: 56px;
    background: var(--color-accent);
    color: var(--color-white);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: var(--shadow-lg);
    z-index: 999;
    transition: background var(--transition), transform var(--transition);
}

.mobile-call-btn:hover {
    background: var(--color-accent-hover);
    transform: scale(1.1);
    color: var(--color-white);
}

.mobile-call-btn svg {
    width: 26px;
    height: 26px;
}

/* --- Summer Banner (Homepage) --- */
.summer-banner-section {
    padding: 48px 0;
    background: var(--color-bg-warm);
    text-align: center;
}

.summer-banner-link {
    display: inline-block;
    text-decoration: none;
    transition: transform 0.2s ease;
}

.summer-banner-link:hover {
    transform: scale(1.01);
}

.summer-banner-image {
    width: 100%;
    max-width: 900px;
    height: auto;
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
}

.summer-banner-details {
    max-width: 800px;
    margin: 32px auto 0;
    text-align: center;
    color: var(--color-text);
    line-height: 1.7;
}

.summer-banner-details h2,
.summer-banner-details h3 {
    color: var(--color-primary);
    margin-bottom: 12px;
}

.summer-banner-details p {
    margin-bottom: 16px;
}

.summer-banner-details a {
    color: var(--color-accent);
    text-decoration: underline;
}

/* --- Summer Programs --- */
.summer-highlights {
    display: grid;
    grid-template-columns: 1fr;
    gap: 20px;
    margin-top: 24px;
}

.summer-card {
    background: var(--color-white);
    padding: 24px;
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    border-left: 4px solid var(--color-accent);
}

.summer-card h3 {
    margin-bottom: 8px;
}

.summer-card p {
    color: var(--color-text-light);
    font-size: 0.95rem;
    margin-bottom: 0;
}

.summer-policies {
    margin-top: 24px;
}

.summer-policies h3 {
    margin-bottom: 12px;
}

.summer-policies ul {
    list-style: none;
    padding: 0;
}

.summer-policies li {
    padding: 8px 0 8px 24px;
    position: relative;
    color: var(--color-text-light);
}

.summer-policies li::before {
    content: '';
    position: absolute;
    left: 0;
    top: 16px;
    width: 8px;
    height: 8px;
    background: var(--color-sage);
    border-radius: 50%;
}

/* --- About Page --- */
.about-content {
    max-width: 800px;
    margin: 0 auto;
}

.about-content p {
    color: var(--color-text-light);
    font-size: 1.05rem;
    margin-bottom: 16px;
}

.about-timeline {
    margin: 40px 0;
}

.timeline-item {
    display: flex;
    gap: 20px;
    margin-bottom: 32px;
    align-items: flex-start;
}

.timeline-year {
    font-family: var(--font-heading);
    font-size: 1.2rem;
    font-weight: 700;
    color: var(--color-accent);
    min-width: 60px;
    flex-shrink: 0;
}

.timeline-content h3 {
    font-size: 1.1rem;
    margin-bottom: 4px;
}

.timeline-content p {
    color: var(--color-text-light);
    font-size: 0.95rem;
    margin-bottom: 0;
}

.about-image {
    border-radius: var(--radius-lg);
    overflow: hidden;
    margin: 32px auto;
    box-shadow: var(--shadow-sm);
    max-width: 560px;
}

.about-image img {
    width: 100%;
    height: auto;
}

.about-text-with-image {
    display: flex;
    flex-direction: column;
    gap: 24px;
    margin-bottom: 40px;
    align-items: center;
}

.about-text-side {
    flex: 1;
}

.about-text-side h2 {
    margin-bottom: 12px;
}

.about-text-side p {
    margin-bottom: 12px;
}

.about-image-side {
    flex-shrink: 0;
    max-width: 320px;
}

.about-image-side img {
    width: 100%;
    height: auto;
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}

.about-figure {
    margin: 0;
}

.about-figure figcaption {
    margin-top: 8px;
    font-size: 0.85rem;
    color: var(--color-text-light);
    font-style: italic;
    text-align: center;
}

.info-cards-single {
    grid-template-columns: 1fr !important;
    max-width: 480px;
    margin: 0 auto;
}

/* --- Info Cards --- */
.info-cards {
    display: grid;
    grid-template-columns: 1fr;
    gap: 20px;
}

.info-card {
    background: var(--color-white);
    padding: 24px;
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    text-align: center;
}

.info-card-icon {
    width: 48px;
    height: 48px;
    margin: 0 auto 12px;
    color: var(--color-accent);
}

.info-card h3 {
    margin-bottom: 8px;
    font-size: 1.1rem;
}

.info-card p {
    color: var(--color-text-light);
    font-size: 0.9rem;
    margin-bottom: 0;
}

/* ============================================
   Responsive Breakpoints (mobile-first)
   ============================================ */

/* Tablet */
@media (min-width: 600px) {
    h1 { font-size: 2.5rem; }
    h2 { font-size: 2rem; }

    .hero h1 { font-size: 2.8rem; }
    .hero { min-height: 450px; padding: 80px 20px; }

    .category-grid { grid-template-columns: repeat(auto-fit, minmax(240px, 280px)); justify-content: center; }
    .gallery-grid { grid-template-columns: repeat(3, 1fr); gap: 16px; }
    .gallery-preview-grid { grid-template-columns: repeat(3, 1fr); gap: 16px; }
    .trust-items { grid-template-columns: repeat(4, 1fr); }
    .info-cards { grid-template-columns: repeat(2, 1fr); }
    .summer-highlights { grid-template-columns: repeat(2, 1fr); }

    .hero-buttons {
        flex-direction: row;
        justify-content: center;
    }

    .cta-buttons {
        flex-direction: row;
        justify-content: center;
    }

    .artist-gallery {
        grid-template-columns: repeat(3, 1fr);
    }

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

    .about-text-with-image {
        flex-direction: row;
        align-items: flex-start;
    }

    .about-text-image-reverse {
        flex-direction: row-reverse;
    }

    .about-image-side {
        max-width: 360px;
    }
}

/* Desktop */
@media (min-width: 768px) {
    .section { padding: 64px 0; }

    .menu-toggle { display: none; }

    .header-nav {
        display: flex !important;
        position: static;
        width: auto;
        /* The mobile drawer caps this at 380px. Resetting width alone leaves
           that cap in force, so the desktop nav was pinned to 380px while its
           contents ran to ~724px — the overflow ran off the right of the page
           and body's overflow-x: hidden clipped it, taking the last item
           (Contact) out of reach. */
        max-width: none;
        height: auto;
        background: transparent;
        box-shadow: none;
        padding: 0;
        overflow: visible;
        align-items: center;
        gap: 8px;
    }

    .nav-menu {
        flex-direction: row;
        align-items: center;
        gap: 0;
    }

    .nav-menu > li {
        border-bottom: none;
        position: relative;
    }

    .nav-menu a {
        padding: 8px 8px;
        font-size: 0.85rem;
    }

    /* Hide the logo text next to the circular image on narrower desktops
       so the full nav fits without overflowing. */
    .header-logo .logo-text {
        display: none;
    }

    .nav-dropdown {
        position: absolute;
        top: 100%;
        left: 0;
        background: var(--color-white);
        box-shadow: var(--shadow-md);
        border-radius: var(--radius);
        min-width: 200px;
        padding: 8px 0;
        display: none;
    }

    .nav-menu > li:hover .nav-dropdown {
        display: block;
    }

    .nav-dropdown a {
        padding: 10px 20px;
        display: block;
        white-space: nowrap;
    }

    /* Hide phone, social, and CTA in header on desktop - already shown in top bar / hero */
    .header-phone,
    .header-actions .header-social,
    .header-cta {
        display: none;
    }

    .header-actions {
        flex-direction: row;
        align-items: center;
        margin-top: 0;
        padding-top: 0;
        border-top: none;
        gap: 16px;
    }

    .about-preview {
        flex-direction: row;
        gap: 48px;
    }

    .about-preview-image {
        flex: 0 0 45%;
    }

    .artist-profile {
        flex-direction: row;
        gap: 48px;
    }

    .artist-portrait {
        flex: 0 0 250px;
    }

    .category-grid { grid-template-columns: repeat(auto-fit, minmax(240px, 280px)); justify-content: center; }

    .footer-grid {
        grid-template-columns: 2fr 1fr 1fr;
    }

    .footer-bottom {
        flex-direction: row;
        justify-content: space-between;
    }

    .mobile-call-btn { display: none; }
}

/* Large Desktop */
@media (min-width: 1024px) {
    h1 { font-size: 3rem; }
    h2 { font-size: 2.25rem; }

    .hero h1 { font-size: 3.2rem; }
    .hero { min-height: 520px; }
    .hero-page { min-height: 320px; }
    .hero-short { min-height: 200px; }

    .gallery-grid {
        grid-template-columns: repeat(4, 1fr);
        gap: 20px;
    }

    .gallery-preview-grid {
        grid-template-columns: repeat(4, 1fr);
        gap: 20px;
    }

    .nav-menu a {
        padding: 8px 12px;
        font-size: 0.9rem;
    }

    .section { padding: 80px 0; }
}

/* --- Announcement Banner --- */
.announcement-banner {
    position: relative;
    background-color: var(--announcement-bg, #c62828);
    color: var(--announcement-fg, #ffffff);
    padding: 10px 0;
    font-family: var(--font-body);
    font-size: 0.95rem;
    font-weight: 600;
    text-align: center;
    overflow: hidden;
}

/* Owner-selectable banner text size (#826). Medium is the size the banner
   rendered at before the setting existed, so rows migrated with the default
   look exactly as they did, and the font-size on .announcement-banner above
   stays as the fallback for markup rendered without a size class.

   These must stay *after* .announcement-banner: both are single-class
   selectors, so source order is the only thing deciding the winner. Moved
   above it, every banner silently renders at 0.95rem whatever the owner
   picked. */
.announcement-size-small { font-size: 0.85rem; }
.announcement-size-medium { font-size: 0.95rem; }
.announcement-size-large { font-size: 1.15rem; }
.announcement-size-xlarge { font-size: 1.4rem; }

.announcement-banner::before {
    content: '';
    position: absolute;
    inset: 0;
    background-image: var(--announcement-pattern, none);
    background-repeat: repeat;
    pointer-events: none;
    opacity: 1;
}

.announcement-pattern-none::before {
    display: none;
}

.announcement-inner {
    position: relative;
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
}

.announcement-message {
    flex: 1;
    text-align: center;
}

.announcement-message p {
    margin: 0;
}

.announcement-message p + p {
    margin-top: 4px;
}

/* Links inherit the banner foreground color so contrast stays correct
   regardless of the chosen background. Underline keeps them recognizable. */
.announcement-message a {
    color: inherit;
    text-decoration: underline;
    text-underline-offset: 3px;
    font-weight: 700;
}

.announcement-message a:hover {
    text-decoration-thickness: 2px;
}

.announcement-close {
    background: none;
    border: none;
    color: inherit;
    font-size: 1.5rem;
    cursor: pointer;
    padding: 0 4px;
    line-height: 1;
    opacity: 0.7;
}

.announcement-close:hover {
    opacity: 1;
}

/* --- Footer Newsletter --- */
.footer-newsletter {
    text-align: center;
    padding: 30px 0;
    border-top: 1px solid rgba(255, 255, 255, 0.15);
    margin-top: 30px;
}

.footer-newsletter h4 {
    font-family: var(--font-heading);
    font-size: 1.3rem;
    margin-bottom: 8px;
}

.footer-newsletter p {
    color: rgba(255, 255, 255, 0.7);
    margin-bottom: 16px;
    font-size: 0.9rem;
}

.newsletter-input-group {
    display: flex;
    max-width: 450px;
    margin: 0 auto;
    gap: 8px;
}

.newsletter-input {
    flex: 1;
    padding: 10px 14px;
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: 6px;
    background: rgba(255, 255, 255, 0.1);
    color: var(--color-white);
    font-size: 0.95rem;
    font-family: var(--font-body);
}

.newsletter-input::placeholder {
    color: rgba(255, 255, 255, 0.5);
}

.newsletter-input:focus {
    outline: 2px solid var(--color-accent);
    outline-offset: -1px;
}

.newsletter-btn {
    padding: 10px 20px;
    background: var(--color-primary);
    color: var(--color-white);
    border: none;
    border-radius: 6px;
    font-size: 0.95rem;
    font-weight: 600;
    cursor: pointer;
    font-family: var(--font-body);
    white-space: nowrap;
    transition: background 0.3s ease;
}

.newsletter-btn:hover {
    background: var(--color-primary-dark);
}

/* The footer is near-black navy, so the slate-blue button above would be blue
   on blue there. White, matching every other button this site puts on a dark
   background. */
.site-footer .newsletter-btn {
    background: var(--color-white);
    color: var(--color-primary);
}

.site-footer .newsletter-btn:hover {
    background: var(--color-bg-warm);
    color: var(--color-primary);
}

/* --- Instructor Cards (public page) --- */

/* Four across at full width, at the owner's request (#828). Nothing here
   pins the count — auto-fill divides the 1200px --max-width container by the
   floor plus the gap, and the old 280px/30px pair came to 1210px for four
   tracks, ten pixels over, which is why it settled on three. 240px/24px
   comes to 1032px and fits, and still steps down to 3/2/1 as the viewport
   narrows. Raising either number pushes it back to three. */
.instructor-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 24px;
}

.instructor-card {
    background: var(--color-white);
    border-radius: 12px;
    overflow: hidden;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
    transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.instructor-card:hover {
    transform: translateY(-4px);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
}

.instructor-card-photo {
    width: 100%;
    height: 280px;
    object-fit: cover;
}

.instructor-card-body {
    padding: 20px;
}

.instructor-card-name {
    font-family: var(--font-heading);
    font-size: 1.3rem;
    margin-bottom: 4px;
}

.instructor-card-specialty {
    color: var(--color-accent);
    font-weight: 600;
    font-size: 0.9rem;
    margin-bottom: 8px;
}

.instructor-card-bio {
    color: var(--color-text-light);
    font-size: 0.9rem;
    line-height: 1.6;
}

/* --- Class buttons above specialty grid --- */
.class-buttons {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 12px;
    margin-bottom: 32px;
}

/* These three are the main way into the class listings, so they are
   deliberately larger than a default .btn — the owner reported them as too
   easy to walk past. */
.class-buttons .btn {
    padding: 16px 36px;
    font-size: 1.15rem;
    font-weight: 700;
}

/* --- Specialty Cards (landing page) --- */
.specialty-grid {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 20px;
}

.specialty-card {
    flex: 0 1 calc((100% - 80px) / 5);
}

@media (max-width: 1100px) {
    .specialty-card {
        flex: 0 1 calc((100% - 60px) / 4);
    }
}

@media (max-width: 860px) {
    .specialty-card {
        flex: 0 1 calc((100% - 40px) / 3);
    }
}

@media (max-width: 560px) {
    .specialty-card {
        flex: 0 1 calc((100% - 20px) / 2);
    }
}

.specialty-card {
    background: var(--color-white);
    border-radius: 12px;
    overflow: hidden;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
    transition: transform 0.3s ease, box-shadow 0.3s ease;
    text-decoration: none;
    color: inherit;
    display: block;
}

.specialty-card:hover {
    transform: translateY(-4px);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
}

.specialty-card-image {
    width: 100%;
    height: 140px;
    object-fit: cover;
}

.specialty-card-body {
    padding: 14px 16px;
    text-align: center;
}

.specialty-card-name {
    font-family: var(--font-heading);
    font-size: 1.1rem;
    margin: 0;
}

.specialty-card-desc {
    color: var(--color-text-light);
    font-size: 0.9rem;
    line-height: 1.5;
}

/* --- Camp Details Text --- */
.camp-details-text {
    max-width: 800px;
    margin: 32px auto 24px;
    font-size: 1rem;
    line-height: 1.7;
    text-align: center;
}

.camp-details-text p { margin-bottom: 0.75rem; }
.camp-details-text p:last-child { margin-bottom: 0; }
.camp-details-text ul, .camp-details-text ol { margin: 0.5rem 0 0.75rem 1.5rem; text-align: left; }
.camp-details-text a { color: var(--color-accent); text-decoration: underline; }


/* --- News & Press Page --- */
.news-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: 48px;
    align-items: start;
}

/* No published newsletters means no rail, and the articles take the full
   width rather than leaving a visibly empty column. */
.news-layout-single {
    grid-template-columns: minmax(0, 1fr);
    max-width: 820px;
    margin: 0 auto;
}

.news-card {
    background: var(--color-white);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
    margin-bottom: 28px;
}

.news-card-media img {
    width: 100%;
    max-height: 380px;
    object-fit: cover;
    display: block;
}

.news-card-body {
    padding: 24px 28px 28px;
}

.news-card-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    font-size: 0.8125rem;
    color: var(--color-text-light);
    margin-bottom: 10px;
}

.news-card-category {
    background: var(--color-sage-light);
    color: var(--color-primary-dark);
    border-radius: 999px;
    padding: 3px 12px;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    font-size: 0.6875rem;
}

.news-card-source {
    font-weight: 600;
    color: var(--color-text);
}

.news-card-source::after {
    content: '·';
    margin-left: 10px;
    font-weight: 400;
    color: var(--color-text-light);
}

.news-card-title {
    font-family: var(--font-heading);
    font-size: 1.5rem;
    line-height: 1.3;
    margin: 0 0 12px;
}

.news-card-title a {
    color: inherit;
    text-decoration: none;
}

.news-card-title a:hover {
    color: var(--color-accent);
}

.news-card-text {
    color: var(--color-text-light);
    line-height: 1.7;
}

.news-card-text > *:first-child { margin-top: 0; }
.news-card-text > *:last-child { margin-bottom: 0; }

.news-card-text a {
    color: var(--color-accent);
}

.news-card-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 16px;
    font-weight: 600;
    color: var(--color-button);
    text-decoration: none;
}

.news-card-link:hover {
    color: var(--color-accent);
}

.news-empty {
    background: var(--color-bg-warm);
    border-radius: var(--radius-lg);
    padding: 48px 32px;
    text-align: center;
}

.news-empty h2 {
    margin-bottom: 12px;
}

.news-empty p {
    color: var(--color-text-light);
    max-width: 46ch;
    margin: 0 auto 24px;
}

.news-sidebar-card {
    background: var(--color-white);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    padding: 24px;
    box-shadow: var(--shadow-sm);
    position: sticky;
    top: calc(var(--header-height) + 24px);
}

.news-sidebar-title {
    font-family: var(--font-heading);
    font-size: 1.25rem;
    margin: 0 0 16px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--color-border);
}

.news-sidebar-list {
    list-style: none;
    padding: 0;
    margin: 0;
}

.news-sidebar-list li {
    padding: 12px 0;
    border-bottom: 1px solid var(--color-border);
}

.news-sidebar-list li:last-child {
    border-bottom: none;
}

.news-sidebar-list a {
    display: block;
    color: var(--color-text);
    text-decoration: none;
    font-weight: 600;
    line-height: 1.4;
}

.news-sidebar-list a:hover {
    color: var(--color-accent);
}

.news-sidebar-list time {
    display: block;
    margin-top: 4px;
    font-size: 0.8125rem;
    color: var(--color-text-light);
}

.news-sidebar-more {
    display: inline-block;
    margin-top: 16px;
    font-weight: 600;
    color: var(--color-button);
    text-decoration: none;
}

.news-sidebar-more:hover {
    color: var(--color-accent);
}

@media (max-width: 900px) {
    .news-layout {
        grid-template-columns: minmax(0, 1fr);
        gap: 32px;
    }

    .news-sidebar-card {
        position: static;
    }
}
