/*
Theme Name: Cape Kiting
Description: Cape Kiting block theme — child of Twenty Twenty-Five. Replaces the Divi theme chrome (header, footer, Custom CSS box) after every page body was moved off the Divi Builder. Rollback = reactivate Divi-child.
Author: Delphius Symington
Template: twentytwentyfive
Version: 1.0.0
Requires at least: 6.6
Requires PHP: 7.4
Text Domain: capekiting
*/

/* Reserve the scrollbar gutter at all times. Opening the mobile menu locks body
   scroll and removes the scrollbar; without a reserved gutter the layout width
   jumps by the scrollbar width (~15px), so the fixed close-X landed ~15px right
   of the hamburger on any scrollbar system (narrow desktop, some Android). */
html {
    scrollbar-gutter: stable;
}

/* ============================================================================
   Design tokens. The brand COLOURS + the cover gradient are defined once in
   theme.json (settings.color.palette / .gradients) so they show up in the editor
   and drive both content and this stylesheet. The tokens below are semantic
   aliases onto those presets — adjust a colour in theme.json, not here. The
   cover gradient drives every content-page hero band (About, Support, Contact,
   Wind Map, Privacy, Terms); station heroes keep their own image + brighter
   overlay and are NOT affected by it. The non-colour tokens (pad/offset) live
   here because they have no theme.json home.
   ============================================================================ */
:root {
    --ck-cover-gradient: var(--wp--preset--gradient--ck-cover);
    --ck-header-bg: var(--wp--preset--color--ink);          /* dark bar — header + footer (Divi primary_nav_bg) */
    --ck-overlay-bg: var(--wp--preset--color--surface-dark); /* dark menu surface — desktop dropdown + mobile overlay */
    --ck-header-pad-x: 24px;      /* header side padding; the mobile close-X right offset must match it */
    --ck-toggle-top: 33px;        /* mobile hamburger/close-X vertical position. Derived: header-pad-y(8)
                                     + (logo-row-height ~90 − icon-size 40)/2. Re-check if the logo size
                                     or header padding changes so the ✕ still lands on the ≡. */
    --ck-drop-offset: 37.5px;     /* desktop dropdown: distance from a top-level item's bottom to the
                                     header bar's bottom edge. Derived: (header 106 − item ~31)/2. Worn as
                                     a transparent border-top on the panel so the VISIBLE dropdown starts
                                     at the bar's bottom edge while the hover hitbox still touches the
                                     item. Re-check with --ck-toggle-top if header geometry changes. */
    /* Menu timing tokens (round 61) — every dropdown/accordion transition
       derives from these three, including the reduced-motion delay-only
       variants (a grace period is a DELAY, not motion, so it survives
       prefers-reduced-motion). */
    --ck-menu-anim: 0.2s;         /* desktop dropdown fade/slide duration */
    --ck-menu-grace: 0.25s;       /* hover-intent CLOSE delay (field norm 200-300ms:
                                     Foundation 250-500, Radix-family ~300) */
    --ck-acc-anim: 0.28s;         /* mobile overlay accordion row animation */
    --ck-acc-grace: 0.08s;        /* accordion COLLAPSE delay: grid-rows animates TRUE height
                                     (unlike max-height, whose dead time accidentally provided
                                     tap-safety), so the collapse waits out the tap explicitly */

    /* Component tokens — repeated literals consolidated (values unchanged).
       Not in theme.json: these are component surfaces, not editor colours. */
    --ck-btn-bg: #474747;         /* .et_pb_button base (Divi all_buttons_bg_color) */
    --ck-btn-bg-hover: #282828;
    --ck-card-bg: #f4f7fa;        /* light card/panel (product gallery, review cards) */
    --ck-card-border: #e2e8ee;
    --ck-dark-panel-bg: #1a1a1a;  /* dark panel/input surface (FAQ boxes, form fields, cards) */
    --ck-dark-panel-border: #333;
    --ck-dark-field-border: #3a3a3a; /* dark input/select border */
    --ck-dark-text: #e9e9e9;      /* body text on dark surfaces */
    --ck-text-muted: #6b7c88;     /* secondary text (product meta, ratings, fine print) */
    --ck-accent: #009ae8;         /* bright action blue (variation price, CTA gradient, matches the kiteometer + YITH accent) */
}
/* TOUCH RULES (post-flip fix 2, operator mobile smoke):
   1. The UA's translucent tap-highlight painted a stray blue box over every
      tapped control (menu icon, menu items, theme toggle). Components provide
      their own feedback; disable the overlay globally — standard practice.
   2. Sticky hover: touch browsers keep :hover applied after a tap until the
      next tap elsewhere, so every stateful hover (sky tint, brightness) read
      as a stuck control. ALL stateful hover rules in this file are therefore
      gated behind @media (hover: hover); their keyboard companions moved to
      :focus-visible (tap-focus doesn't match it, keyboard does). NEUTRALIZER
      hover rules (the ones stripping core's grey toggle boxes) stay UNGATED
      on purpose — gating those would reintroduce the boxes on touch. */
html {
    -webkit-tap-highlight-color: transparent;
}
/* Theme-aware cover gradient: the light theme lifts the same two hues a shade
   (the dark-theme gradient reads too heavy on a white page). Both presets live
   in theme.json; the covers consume whichever this token resolves to. */
body.light-theme {
    --ck-cover-gradient: var(--wp--preset--gradient--ck-cover-light);
}
/* Content covers = a .ck-hero with NO background image. Force the global
   gradient onto their overlay span (beats the per-page inline colour/gradient).
   NB: match the image background as `.wp-block-cover__image-background` (ANY tag)
   — stations use an <img>, but the home hero is a PARALLAX <div> with a
   background-image; the old `img.` selector missed it and the opaque gradient
   painted over the home photo. */
.ck-hero:not(:has(.wp-block-cover__image-background)) > .wp-block-cover__background {
    background: var(--ck-cover-gradient) !important;
}

/* ============================================================================
   Global focus handling. The theme ships a solid `outline: 2px #101010` focus
   ring that fires on EVERY click/tap, leaving a visible border on the FAQ
   <details> summary, the mobile hamburger, the menu chevron, etc. Suppress it
   for pointer focus only (:focus:not(:focus-visible)) so keyboard users keep a
   ring. Resolves the recurring "border after clicking" globally.
   ============================================================================ */
:focus:not(:focus-visible) {
    outline: none !important;
}

/* ============================================================================
   Site chrome — header + footer (replaces Divi's header.php / footer.php)
   ============================================================================ */

/* Sticky site header — the sticky lives on the TEMPLATE-PART WRAPPER
   (.wp-site-blocks > header), NOT on .ck-site-header: a sticky element can
   only travel within its PARENT, and the wrapper is exactly bar-height, so
   sticky on the inner bar had zero room to move and the header simply
   scrolled away (caught 2026-07-23 — it had never actually stuck). The
   wrapper is a direct child of the full-height flex column, so it pins for
   the whole page. */
.wp-site-blocks > header {
    position: sticky;
    top: 0;
    /* This wrapper is a stacking context, so its z-index CAPS everything
       inside it — including the full-screen mobile menu overlay and the
       desktop dropdowns. 10000 beats the wind map stack (notice card 1100,
       Leaflet controls 1000, mobile config panel 9999), which otherwise
       painted OVER the open menu; it stays below WP's admin bar (99999). */
    z-index: 10000;
}
/* WP admin bar offset (logged-in users who get the toolbar): only where the
   admin bar is actually FIXED (>600px). At <=600px core makes #wpadminbar
   position:absolute — it scrolls away with the page — so an offset there
   leaves a content-filled gap floating above the pinned header (caught on
   mobile 2026-07-23) and breaks the ≡/✕ alignment. Guests resolve the var
   to the 0px fallback. */
@media ( min-width: 601px ) {
    .wp-site-blocks > header {
        top: var(--wp-admin--admin-bar--height, 0px);
    }
}
.ck-site-header {
    background: var(--ck-header-bg);     /* the white logo needs a dark bar */
    padding: 8px var(--ck-header-pad-x); /* full-bleed dark bar; edge gap on narrow screens */
    box-shadow: 0 1px 6px rgba(0, 0, 0, 0.35);
}
/* NB deliberately NO shrink-on-scroll: the bar stays full-size while pinned.
   Tried twice (scroll-driven interpolation, then a scroll-state(stuck) flip,
   2026-07-23) — anything that changes the HEADER'S LAYOUT HEIGHT on scroll
   re-maps the scrollbar while the thumb is being dragged (continuous drift or
   boundary jitter). Decision: full-size always. Do not re-pitch unless the
   shrink is transform-only (no layout change). */
/* Divi capped the header content to the content width and centred it; the bar
   background stayed full-bleed. Without this the logo/menu stretch to the edges
   on ultra-wide screens. Cap the inner (logo + nav) to the 1080 content width. */
.ck-site-header .ck-header-inner {
    max-width: 1080px;
    margin-left: auto;
    margin-right: auto;
}
/* Nav is Rajdhani like the old Divi menu; white links on the dark bar
   (Divi menu_link #fff, hover #99cde8). Must beat the generic
   `body.dark-theme a` rule on dark-theme pages. */
.ck-site-header .wp-block-navigation {
    font-family: var(--wp--preset--font-family--rajdhani), sans-serif;
    font-size: 17px;
    font-weight: 500;
    text-transform: uppercase;   /* Divi primary_nav_font_style = uppercase */
    letter-spacing: normal;
}
/* Nav text — top links, submenu-parent toggles ("Wind"/"About"), dropdown items,
   and the dropdown chevron — all white, no underline, with a low-cost colour
   fade on hover. */
.ck-site-header .wp-block-navigation a,
.ck-site-header .wp-block-navigation .wp-block-navigation-item__content,
.ck-site-header .wp-block-navigation .wp-block-navigation__submenu-icon {
    color: #ffffff;
    text-decoration: none;
    transition: color .18s ease;
}
.ck-site-header .wp-block-navigation__submenu-icon svg {
    fill: currentColor;
}
/* Hover: the whole item — its link/toggle AND its chevron (which is a separate
   sibling element) — turn the active blue TOGETHER, so the arrow never lights up
   on its own. No underline on hover either. Hover variants live behind
   (hover:hover) — on touch the sticky :hover kept items sky until the next tap
   (post-flip fix 2); keyboard affordance is the :focus-visible rule below. */
@media (hover: hover) {
    .ck-site-header .wp-block-navigation a:hover,
    .ck-site-header .wp-block-navigation .wp-block-navigation-item:hover > a,
    .ck-site-header .wp-block-navigation .wp-block-navigation-item:hover > .wp-block-navigation-item__content,
    .ck-site-header .wp-block-navigation .wp-block-navigation-item:hover > .wp-block-navigation__submenu-icon {
        color: var(--wp--preset--color--sky);
        text-decoration: none;
    }
}
.ck-site-header .wp-block-navigation a:focus-visible,
.ck-site-header .wp-block-navigation .current-menu-item > a {
    color: var(--wp--preset--color--sky);
    text-decoration: none;
}
/* No focus box on the nav or the site logo (operator dislikes the outline a
   click leaves). The colour change above is the focus/hover affordance, so
   keyboard users still see the active item. */
.ck-site-header .wp-block-navigation a:focus,
.ck-site-header .wp-block-navigation a:focus-visible,
.ck-site-header .wp-block-navigation .wp-block-navigation-item__content:focus,
.ck-site-header .wp-block-navigation .wp-block-navigation-item__content:focus-visible,
.ck-site-header .wp-block-site-logo a:focus,
.ck-site-header .wp-block-site-logo a:focus-visible {
    outline: none;
    box-shadow: none;
}
/* Dropdown submenus + mobile overlay: dark with white text (Divi used #1e1e1e). */
.ck-site-header .wp-block-navigation__submenu-container {
    background-color: var(--ck-overlay-bg) !important;
    border: none !important;
    /* Top-level items stay UPPERCASE (Divi), but dropdown items — the location
       names + About/Privacy/Terms — read as title case (their source text). */
    text-transform: none;
}
.ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content {
    background-color: var(--ck-overlay-bg);
}
/* Fill the whole screen with the dark panel (Divi used min-height:100vh); without
   this the panel only covers the item list and the page shows through below.
   The block defaults the overlay to a WHITE background when no overlay colour is
   set (`.wp-block-navigation:not(.has-background) …is-menu-open`), which beat a
   plain rule — so the dark only reached the inner content wrapper and white
   showed below the short (collapsed) list. Force the fixed container dark. */
.ck-site-header .wp-block-navigation__responsive-container.is-menu-open {
    min-height: 100dvh;
    background-color: var(--ck-overlay-bg) !important;
}
/* While the mobile menu is open the block locks scroll (`html.has-modal-open`,
   overflow:hidden), which removes the scrollbar. `scrollbar-gutter:stable` keeps
   the 15px gutter reserved (so the close-X doesn't shift) but that empty gutter
   then shows the page background as a strip beside the dark overlay. Colour the
   root the overlay's shade while the modal is open so the strip blends in. */
html.has-modal-open,
html.has-modal-open body {
    background-color: var(--ck-overlay-bg);
}
/* (Overlay link colour + the ≡/✕ icon colour come from the base nav rule above
   and the mobile icon rules below — no separate overrides needed here.) */
/* Submenu parents ("Wind", "About") render as <button> toggles
   (openSubmenusOnClick) — strip the default button background/border so they
   read as plain menu items like the Divi non-link parents did. */
/* BACKGROUND stripped in all interaction states (round 63): with the toggle
   clickable again, button hover rules painted a grey block behind the label
   (measured rgb(107,107,107)) — pointer-events:none used to mask this. The
   item's own hover affordance is the sky text/icon colour.
   NB background ONLY in the state variants: the shape reset lives in the
   separate base rule below, because putting padding-inline:0 on the :hover
   variants out-specified core's own padding-right (the icon's reserved
   room) and slid the label under the chevron on hover (round 64, measured
   14.45px -> 0). */
.ck-site-header .wp-block-navigation-submenu__toggle,
.ck-site-header .wp-block-navigation-submenu__toggle:hover,
.ck-site-header .wp-block-navigation-submenu__toggle:focus,
.ck-site-header .wp-block-navigation-submenu__toggle:active,
body.dark-theme .ck-site-header .wp-block-navigation-submenu__toggle:hover,
body.dark-theme .ck-site-header .wp-block-navigation-submenu__toggle:focus,
.ck-site-header button.wp-block-navigation-item__content {
    background-color: transparent !important;
}
.ck-site-header .wp-block-navigation-submenu__toggle,
.ck-site-header button.wp-block-navigation-item__content {
    border: 0;
    padding-inline: 0;   /* core's more-specific padding-right (icon room) still wins, in EVERY state */
}

/* Header CTA — the membership sign-up as a real button (industry convention:
   one filled conversion button at the far right; Login stays quiet text).
   Reuses the product page's money-button gradient — same action, second
   placement. Must sit AFTER the nav colour/hover rules: the hover selectors
   tie at (0,4,1) and source order breaks the tie. Hidden for logged-in
   members by the ck-nav-signup render filter in functions.php. */
.ck-site-header .wp-block-navigation .ck-nav-signup a {
    background: linear-gradient(135deg, #006cd8, var(--ck-accent));
    color: #ffffff;
    border-radius: 8px;
    padding: 9px 18px;
    font-weight: 600;
    transition: filter 0.2s ease;
}
@media (hover: hover) {
    .ck-site-header .wp-block-navigation .ck-nav-signup a:hover,
    .ck-site-header .wp-block-navigation .ck-nav-signup:hover > a {
        color: #ffffff;
        filter: brightness(1.1);
    }
}
.ck-site-header .wp-block-navigation .ck-nav-signup a:focus-visible {
    color: #ffffff;
    filter: brightness(1.1);
}

/* In-page anchors (e.g. /support/#contact) must not land under the sticky
   header: reserve the bar height plus breathing room, and the admin bar when
   present. */
:target,
a[name] {
    /* a[name] too (post-flip fix 3): the Word-imported Privacy/Terms TOCs
       anchor on <a name="_Toc…">, and Chrome never matches those with
       :target — so their jumps landed under the sticky header while
       id-anchors (e.g. /support/#contact) worked. scroll-margin applies to
       the scrolled-to element either way. */
    scroll-margin-top: calc(122px + var(--wp-admin--admin-bar--height, 0px));
}

/* ---- Desktop dropdowns: HYBRID hover + click (round 61, field alignment) ---
   Hover opens with intent (fade+slide in, --ck-menu-grace close delay), AND
   the toggle button is clickable: a click flips core's aria-expanded, which
   PINS the panel open until an outside click/Escape (core's own dismiss
   handling) — the disclosure behaviour the a11y guidance prefers, and the
   working path for touch-screen laptops at desktop widths that previously
   depended on emulated sticky-hover. (Until round 61 the toggle was
   pointer-events:none for Divi hover-only parity.) Keyboard: Tab focuses the
   toggle (closed), Enter/Space opens, Escape closes - the WAI-ARIA
   disclosure contract. */
@media ( min-width: 601px ) {
    .ck-site-header .wp-block-navigation__submenu-container {
        /* Centre the dropdown under its parent item (left:50% + translateX(-50%))
           instead of the block default (which sets its own `left`, so !important
           is needed), and give it real vertical breathing room top and bottom.
           translateY carries the slide-in. */
        left: 50% !important;
        right: auto !important;
        padding-top: 12px;
        padding-bottom: 12px;
        /* Start the VISIBLE panel at the header bar's bottom edge, not at the
           item's bottom mid-bar: a transparent border-top spans the remaining
           bar height (background clipped off it), keeping the panel's hitbox
           attached to the item so hover survives the pointer's trip down.
           !important beats the `border: none !important` in the base rule. */
        border-top: var(--ck-drop-offset) solid transparent !important;
        background-clip: padding-box;
        /* Keep the box REAL while closed. openSubmenusOnClick collapses closed
           submenus to width:0;height:0;overflow:hidden — none of which is
           transitionable, so leaving that in place made the CLOSE snap shut
           (the panel clipped away before the fade could run). Hidden-ness is
           carried by opacity/visibility alone, so open AND close both animate;
           min-width keeps the longest location on one line. */
        width: auto !important;
        height: auto !important;
        overflow: visible !important;
        min-width: 210px;
        /* Subtle blue seam where the bar meets the open panel: an inset shadow
           paints at the padding-box top — exactly the visible top edge, below
           the transparent spacer border. Sky = the nav hover accent. */
        box-shadow: inset 0 2px 0 0 var(--wp--preset--color--sky);
        opacity: 0;
        visibility: hidden;
        transform: translateX(-50%) translateY(8px);
        /* visibility TRANSITIONS with a duration: interpolation holds `visible`
           while either endpoint is visible, so closing stays visible for the
           whole fade, flipping only at the end. !important is required: core's
           own submenu rule (.wp-block-navigation .has-child
           .wp-block-navigation__submenu-container, 0-3-0) otherwise outranks
           this (0-2-0) with `opacity .1s linear` — an opacity-ONLY list under
           which visibility snapped and the close vanished instantly.
           The --ck-menu-grace DELAY is the hover-intent grace (rounds 59/61):
           this list only applies to the CLOSE (the open rule carries its own
           no-delay list), so a pointer cutting diagonally across a sibling
           item, or jittering off the panel mid-click, has 250ms of
           fully-visible panel to come back to — re-entering during the grace
           reopens with zero flicker because opacity has not started moving. */
        transition: opacity var(--ck-menu-anim) ease var(--ck-menu-grace),
                    transform var(--ck-menu-anim) ease var(--ck-menu-grace),
                    visibility var(--ck-menu-anim) linear var(--ck-menu-grace) !important;
    }
    .ck-site-header .wp-block-navigation-item.has-child:hover > .wp-block-navigation__submenu-container,
    .ck-site-header .wp-block-navigation-item.has-child:has( > .wp-block-navigation-submenu__toggle[aria-expanded="true"] ) > .wp-block-navigation__submenu-container {
        /* Two open paths (round 62): hover (with intent) and the aria-expanded
           disclosure state (Enter/Space/click on the toggle; Escape and
           outside interactions close it). The old :has(:focus-visible)
           auto-open is GONE - it fought the disclosure contract: pressing
           Escape upgrades the focused toggle to :focus-visible, so the CSS
           held the panel open even as core un-pinned aria (measured). The
           WAI-ARIA keyboard contract is Tab = focus only, Enter opens. */
        opacity: 1;
        visibility: visible;
        transform: translateX(-50%) translateY(0);
        /* Pin must not resize the panel: core's aria-open styles force
           width/min-width 200px, which visibly snapped the hover-open 210px
           panel narrower on click (round 63, measured). */
        width: auto !important;
        min-width: 210px !important;
        /* Opening stays INSTANT: this higher-specificity list (no delay)
           applies while open; the base rule's delayed list governs the
           close. Both !important for the same core-specificity reason. */
        transition: opacity var(--ck-menu-anim) ease,
                    transform var(--ck-menu-anim) ease,
                    visibility var(--ck-menu-anim) linear !important;
    }
    /* Sibling hand-off (round 61): the grace exists for LEAVING the menu
       area, not for moving BETWEEN submenu parents — without this the old
       panel lingered its full grace beside the new one (two dropdowns side
       by side, seen greeting → Wind Spots). The moment ANOTHER submenu
       parent is hovered, any not-hovered panel yields instantly (the
       Radix-style switch). Wins on specificity in BOTH motion modes; pinned
       (aria-expanded) panels are unaffected — their open state comes from
       the aria rule, not :hover. */
    .ck-site-header .wp-block-navigation:has( .wp-block-navigation-item.has-child:hover ) .wp-block-navigation-item.has-child:not( :hover ) > .wp-block-navigation__submenu-container {
        transition: none !important;
    }
    /* Light-dismiss is instant too: nav-dismiss.js stamps this class for the
       moment it un-pins a clicked-open panel (outside click), so the panel
       vanishes at once instead of riding the hover grace — a fading panel
       could swallow the user's next click. */
    .ck-site-header .wp-block-navigation.ck-nav-instant .wp-block-navigation__submenu-container {
        transition: none !important;
    }
    /* Click-to-CLOSE on a hover device (round 63): un-pinning while the
       pointer still sits on the toggle used to look like a dead click — the
       hover path immediately held the panel open again. nav-dismiss.js
       stamps ck-hover-muted on the item after an un-pinning click and clears
       it on mouseleave; while muted, hover does not reopen. Outranks the
       open rule (extra class).
       The :not() is load-bearing (round 65): the mute exists to stop
       HOVER-opening only — without it, a third click re-pinned aria but the
       lingering mute (mouseleave never fired) kept hiding the panel, so
       repeated clicks could "never open it again". A pinned panel can never
       be muted. */
    .ck-site-header .wp-block-navigation-item.has-child.ck-hover-muted:not( :has( > .wp-block-navigation-submenu__toggle[aria-expanded="true"] ) ):hover > .wp-block-navigation__submenu-container {
        opacity: 0;
        visibility: hidden;
        transition: none !important;
    }
}
/* Mobile hamburger: assert the open button shows below the 600px nav breakpoint
   (this enqueued stylesheet out-prioritises the block's own rule), and drop the
   collapsed inline menu from flow so it can't displace the button off-screen
   (the block's hidden-by-default class isn't emitted for a theme-authored nav). */
@media ( max-width: 600px ) {
    .ck-site-header .wp-block-navigation__responsive-container-open:not( .always-shown ) {
        display: flex !important;
    }
    .ck-site-header .wp-block-navigation__responsive-container:not( .is-menu-open ) {
        display: none !important;
    }
    .ck-site-header .wp-block-navigation {
        flex-basis: auto !important;
        min-width: 0 !important;
    }

    /* Hamburger icon: the block's default sits in a grey box and is only two bars.
       Strip the box and draw a clean three-line icon (Divi's ≡) in white. */
    .ck-site-header .wp-block-navigation__responsive-container-open,
    .ck-site-header .wp-block-navigation__responsive-container-close {
        background: transparent !important;
        border: 0 !important;
        padding: 0 !important;
        color: #ffffff;
        outline: none !important;   /* no focus box on the icon toggles (the block
                                       returns focus to the opener on close) */
        box-shadow: none !important;
    }
    .ck-site-header .wp-block-navigation__responsive-container-open {
        width: 40px;
        height: 40px;
        align-items: center;
        justify-content: center;
    }
    .ck-site-header .wp-block-navigation__responsive-container-open svg {
        display: none;             /* replace the 2-bar SVG with a 3-line icon */
    }
    .ck-site-header .wp-block-navigation__responsive-container-open::before {
        content: "";
        width: 28px;
        height: 3px;
        background: #ffffff;
        border-radius: 2px;
        box-shadow: 0 -9px 0 #ffffff, 0 9px 0 #ffffff;
    }
    /* Close (X): the block drops it higher up and as a thin 24px SVG, so it jumps
       position and style vs the hamburger. Pin it to the hamburger's exact spot
       (--ck-toggle-top / --ck-header-pad-x, 40x40) and draw the X from the same
       28px/3px white bars, so tapping toggles a matching icon in place. */
    .ck-site-header .wp-block-navigation__responsive-container-close {
        position: fixed;
        top: var(--ck-toggle-top);
        right: var(--ck-header-pad-x);
        width: 40px;
        height: 40px;
    }
    /* WP admin bar (post-flip fix 3, reworked 3c): the X is position:fixed,
       so it ignores the html margin-top the bar adds — at the top of the page
       it slid UNDER the bar. A CONSTANT offset was wrong too (operator catch):
       on phones the bar is position:absolute and scrolls away, which left the
       X floating low after any scroll. nav-dismiss.js measures the bar's
       VISIBLE overlap each time the overlay opens (background scroll is
       locked while open, so once is exact) and publishes it here. */
    body.admin-bar .ck-site-header .wp-block-navigation__responsive-container-close {
        top: calc(var(--ck-toggle-top) + var(--ck-adminbar-overlap, 0px));
    }
    .ck-site-header .wp-block-navigation__responsive-container-close svg {
        display: none;
    }
    .ck-site-header .wp-block-navigation__responsive-container-close::before,
    .ck-site-header .wp-block-navigation__responsive-container-close::after {
        content: "";
        position: absolute;
        top: 50%;
        left: 50%;
        width: 28px;
        height: 3px;
        background: #ffffff;
        border-radius: 2px;
    }
    .ck-site-header .wp-block-navigation__responsive-container-close::before {
        transform: translate(-50%, -50%) rotate(45deg);
    }
    .ck-site-header .wp-block-navigation__responsive-container-close::after {
        transform: translate(-50%, -50%) rotate(-45deg);
    }

    /* Subtle ≡ ↔ ✕ transition. Both icons sit at the same spot, so fade+spin the
       hamburger out as the X spins in (and reverse on close). The hamburger is
       hidden behind the overlay while open, so on open you see the X spin in; on
       close the overlay clears and the hamburger spins back in. */
    @keyframes ck-burger-x-in {
        from { opacity: 0; transform: rotate(-90deg) scale(.6); }
        to   { opacity: 1; transform: rotate(0) scale(1); }
    }
    .ck-site-header .wp-block-navigation__responsive-container-open {
        transition: transform .3s ease, opacity .25s ease;
    }
    .ck-site-header .wp-block-navigation__responsive-container-open:has( ~ .wp-block-navigation__responsive-container.is-menu-open ) {
        opacity: 0;
        transform: rotate(90deg) scale(.6);
    }
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close {
        animation: ck-burger-x-in .3s ease both;
    }

    /* Divi's mobile menu collapsed its submenus behind a +/- toggle. The block
       overlay instead dumps every submenu item into one long flat list. Hide the
       submenu items and only reveal them when their chevron is expanded.
       Accordion via ANIMATED max-height, NOT display:none (round 60): tapping a
       link BELOW an open submenu focuses it, WP's nav script collapses the
       submenu on that focus, and an instant collapse yanked the link ~420px up
       BETWEEN mousedown and click — the click then fired on empty space and the
       tap was lost (measured: Support jumped 577px→156px in 30ms). Animated,
       the link has moved only a few px when the click lands (and the collapsing
       list stays clickable through the fade, visibility flips at the END).
       border-box so max-height:0 swallows the band's padding; visibility:hidden
       keeps the closed list out of the tab order like display:none did. */
    /* Mechanism (round 61): the GRID-ROWS 0fr→1fr pattern — the current
       cross-browser standard for animating to TRUE content height (replaces
       the round-60 max-height cap, which animated through guessed empty
       space). The parent ITEM is a two-row grid: row 1 the full-width toggle,
       row 2 the submenu track that animates 0fr→1fr; the list itself only
       needs min-height:0 + overflow:hidden to follow its track. !important on
       the mechanism properties: core's overlay CSS force-shows submenu
       content — the same war the old display:none !important fought. */
    /* Collapse = short grace + ease-in (near-zero movement while a tap's
       click event lands); expand = instant-start ease via its own list. */
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item.has-child {
        display: grid !important;
        grid-template-rows: auto 0fr;
        /* start, NOT the default stretch (round 68): mid-transition Chrome
           interpolates the item height AND the fr unit together, so there is
           leftover free space each frame — stretch pours it into the AUTO row
           and the parent label itself sagged ~40px down and back during the
           animation. start drops the leftover below the band instead. */
        align-content: start;
        transition: grid-template-rows var(--ck-acc-anim) ease-in var(--ck-acc-grace) !important;
    }
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item.has-child:has( > .wp-block-navigation-submenu__toggle[aria-expanded="true"] ) {
        grid-template-rows: auto 1fr;
        transition: grid-template-rows var(--ck-acc-anim) ease !important;
    }
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container {
        display: flex !important;
        box-sizing: border-box;
        min-height: 0;
        align-self: stretch;   /* follow the animating track: the overlay's
                                  align-items:center otherwise left this box
                                  (and its band background) full-height while
                                  the track shrank under it (round 63) */
        overflow: hidden !important;
        visibility: hidden !important;
        transition: visibility var(--ck-acc-anim) linear var(--ck-acc-grace) !important;
    }
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item.has-child:has( > .wp-block-navigation-submenu__toggle[aria-expanded="true"] ) > .wp-block-navigation__submenu-container {
        visibility: visible !important;
        transition: none !important;   /* opening reveals instantly */
    }
    /* INTENTIONAL collapse must feel immediate (round 63): the grace+ease-in
       is tap-safety for FOCUS-driven collapses (tapping another item), but on
       a direct toggle tap it read as lag. nav-dismiss.js stamps ck-acc-instant
       on the item for toggle taps: fast ease, no grace. (The expanded rules
       outrank these, so OPENING is unaffected.) */
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item.has-child.ck-acc-instant {
        transition: grid-template-rows 0.18s ease !important;
    }
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item.has-child.ck-acc-instant > .wp-block-navigation__submenu-container {
        transition: visibility 0.18s linear !important;
    }
    /* Make the ENTIRE parent row the tap target — not just the label. The toggle
       button fills the row width and the chevron is drawn INSIDE it (::after), so
       the block's separate chevron <span> is hidden. Tapping anywhere on the row
       (label, arrow, or empty space) expands/collapses it. */
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item.has-child > .wp-block-navigation__submenu-icon {
        display: none;
    }
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-submenu__toggle,
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-submenu__toggle:hover,
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-submenu__toggle:focus {
        pointer-events: auto;
        display: flex;
        width: 100%;
        margin: 0;
        justify-content: center;
        align-items: center;
        gap: 12px;
        /* The block puts a hover/focus background on the toggle; harmless when the
           button was label-width, but a full-width grey band now. Keep it clear. */
        background-color: transparent !important;
    }
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-submenu__toggle::after {
        content: "";
        flex: none;
        width: 9px;
        height: 9px;
        border-right: 2px solid currentColor;
        border-bottom: 2px solid currentColor;
        transform: rotate(45deg);          /* ⌄ collapsed */
        margin-top: -3px;                  /* optical centring of the caret */
        /* The caret must not COUNT towards centring (post-flip fix 2): its
           9px box + the 12px flex gap pushed the label 10.5px left of the
           other items' true centre. The negative right margin gives the caret
           zero net width, so the label centres alone and the caret hangs to
           its right — same alignment as the plain menu rows. */
        margin-right: -21px;
        transition: transform .2s ease;
    }
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-submenu__toggle[aria-expanded="true"]::after {
        transform: rotate(-135deg);        /* ⌃ expanded */
        margin-top: 3px;
    }
    /* Item rhythm + size: centred, Title Case, 22px (post-flip fix 2 — the
       operator found 20px uppercase hard to hit and hard to read; Title Case
       + the size bump grow every tap target). Desktop keeps uppercase. */
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container {
        gap: 4px;
        padding-top: 8px;
    }
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item {
        font-size: 22px;    /* ALL levels — dropdown items match the top level,
                               as the original menu did (round 66; the selector
                               reaches nested items too, keep it override-free) */
        text-transform: none;
    }
    /* Give the expanded dropdown its own slightly-lighter band so its items read
       as a distinct group from the main menu items. The band's breathing room is
       child MARGIN, not container padding: a box can't shrink below its own
       padding, so padding floored the collapsed 0fr track at 16px — a ghost gap
       under every has-child item that broke the overlay's rhythm (round 66).
       Margins are content — they clip with the track. */
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item.has-child > .wp-block-navigation__submenu-container {
        background-color: #2c2c2c !important;
        padding-top: 0 !important;
        padding-bottom: 0 !important;
        border-radius: 8px;
    }
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item.has-child > .wp-block-navigation__submenu-container > :first-child {
        margin-top: 6px;
    }
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item.has-child > .wp-block-navigation__submenu-container > :last-child {
        margin-bottom: 10px;
    }
    /* Dropdown ITEM rhythm (round 67): core gives nested links `.5em 1em`
       padding — at the overlay's 20px font that became 10px vertical, a 57px
       pitch that read as huge gaps (round 66's font bump exposed it). 2px
       vertical = the same 38px pitch as the top-level rows. !important: the
       core rule is a long class chain the overlay scope alone can't outrank. */
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
        padding: 2px 20px !important;
    }
    /* ...and core ALSO stacks a 3px margin between submenu items (battery
       catch, round 67) — zero it so the pitch is exactly the top level's 38px.
       :not(:last-child) mirrors core's selector; the band's 6/10px breathing
       room (:first-child margin-top / :last-child margin-bottom) is untouched. */
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container .wp-block-navigation-item:not(:last-child) {
        margin-bottom: 0 !important;
    }
    /* The signup CTA must read as a BUTTON in the overlay too (round 67):
       core's overlay reset zeroes link padding at HIGHER specificity than the
       desktop pill rule, so the gradient shrank to a text-tight blob. Restore
       real button padding (a touch wider than desktop for the tap target). */
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .ck-nav-signup .wp-block-navigation-item__content {
        padding: 9px 22px !important;
    }
}
/* Full-screen overlay menu: the header nav is right-justified for desktop, which
   in the overlay pushes long labels off the right edge — center everything,
   including the "Wind"/"About" submenu-parent toggles. */
.ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container,
.ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container,
.ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item {
    align-items: center;
    justify-content: center;
    text-align: center;
    width: 100%;
}
/* (Submenu-toggle centring lives with the full-row tap-target rules in the
   mobile media query above — width:100%, margin:0, justify-content:center.) */
.ck-site-header .wp-block-site-logo img {
    width: 90px;
    height: auto;
}

/* ---- Header theme toggle (dark/light) --------------------------------------
   Flips the CapeKiting theme preference; assets/js/theme-toggle.js reveals the
   button, saves via shared.js, and reloads (kiteometer-settings parity). The
   icon shows the theme you'll switch TO: sun while dark, moon while light.
   All rules carry the .ck-site-header scope so they out-specify the generic
   `body.dark-theme button` background rule (same clash the nav submenu toggles
   had) — without it the icon sits in a grey box in dark theme. */
.ck-header-right {
    gap: 6px;
}
.ck-site-header .ck-theme-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    border: 0;
    background: transparent;
    color: #ffffff;
    cursor: pointer;
    transition: color .18s ease;
}
.ck-site-header .ck-theme-toggle[hidden] {
    /* Ships hidden until the JS binds — but keep the 40px BOX in layout and
       hide with visibility, so the reveal is paint-only. display:none here
       made the button POP IN and shift the nav items left whenever the footer
       script ran after first paint (deterministic on Wind Map, whose snippet's
       synchronous CDN scripts stall the parser; intermittent elsewhere). A
       no-JS visitor gets an invisible 40px gap instead of a dead control. */
    visibility: hidden;
}
@media (hover: hover) {
    .ck-site-header .ck-theme-toggle:hover {
        color: var(--wp--preset--color--sky);
        background: transparent;
    }
}
.ck-site-header .ck-theme-toggle:focus-visible {
    color: var(--wp--preset--color--sky);
    background: transparent;
}
.ck-site-header .ck-theme-toggle:disabled {
    opacity: 0.5;    /* save-and-reload in flight */
}
.ck-site-header .ck-theme-toggle svg {
    display: block;
    width: 22px;
    height: 22px;
}
.ck-site-header .ck-theme-toggle .ck-icon-sun { display: none; }
body.dark-theme .ck-site-header .ck-theme-toggle .ck-icon-sun { display: block; }
body.dark-theme .ck-site-header .ck-theme-toggle .ck-icon-moon { display: none; }
/* Home page: the content is fixed-palette (hero image + tinted bands), so a
   theme toggle would visibly do nothing there — hide it. visibility (not
   display:none) keeps its 40px box in layout so the menu items sit at the SAME
   position as on every other page (no cross-page jump). */
body.home .ck-site-header .ck-theme-toggle {
    visibility: hidden;
    pointer-events: none;
}
/* (The toggle shows on WooCommerce pages too — snippet 19's forced-light-on-Woo
   branch was removed 2026-07-23; Woo dark styling lives in the Woo dark section
   further down.) */
/* Desktop: toggle sits to the RIGHT of the menu. On mobile it keeps its DOM
   position BEFORE the nav, so the hamburger stays the rightmost element at
   --ck-header-pad-x from the edge — the fixed close-X is pinned to that spot. */
@media ( min-width: 601px ) {
    .ck-site-header .ck-theme-toggle {
        order: 2;
    }
}

/* Respect reduced-motion for the chrome animation this theme ADDS (nav colour
   fades, dropdown slide, ≡/✕ spin). The hero parallax is left alone — it
   deliberately keeps Divi parity (see the .ck-hero parallax rules). */
@media ( prefers-reduced-motion: reduce ) {
    /* NB the submenu-container is deliberately NOT in this kill list: its
       hover-intent grace is a DELAY, not motion, and killing it re-broke the
       round-59 diagonal-move/click fixes for reduced-motion users (caught
       when the test box itself started reporting reduce — round 60). It gets
       its own motionless-but-delayed rules below and after this block. */
    .ck-site-header .wp-block-navigation a,
    .ck-site-header .wp-block-navigation .wp-block-navigation-item__content,
    .ck-site-header .wp-block-navigation .wp-block-navigation__submenu-icon,
    .ck-site-header .wp-block-navigation__responsive-container-open,
    .ck-site-header .wp-block-navigation-submenu__toggle::after,
    .ck-site-header .ck-theme-toggle {
        /* !important so this also outranks other !important transitions. */
        transition: none !important;
    }
    /* Mobile overlay accordion: keep the round-60 CLICK-SAFETY without motion —
       the collapse becomes a delay-only snap (waits out the tap, no animation);
       opening stays instant. Covers BOTH mechanism carriers: the item's grid
       rows and the list's visibility. */
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item.has-child {
        transition: grid-template-rows 0s linear var(--ck-acc-anim) !important;
    }
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item.has-child:has( > .wp-block-navigation-submenu__toggle[aria-expanded="true"] ) {
        transition: none !important;
    }
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container {
        transition: visibility 0s linear var(--ck-acc-anim) !important;
    }
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item.has-child:has( > .wp-block-navigation-submenu__toggle[aria-expanded="true"] ) > .wp-block-navigation__submenu-container {
        transition: none !important;
    }
    /* Intentional toggle taps snap immediately under reduced motion too —
       the delay-snap is tap-safety for focus-driven collapses only. */
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item.has-child.ck-acc-instant,
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item.has-child.ck-acc-instant > .wp-block-navigation__submenu-container {
        transition: none !important;
    }
    .ck-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close {
        animation: none;
    }
}
/* Desktop dropdown under reduced motion: no fade, no slide, but the round-59
   hover-intent grace SURVIVES as a delay-only snap — the panel holds fully
   visible (and clickable) for grace+anim after hover loss (the same total
   window the animated path gives), then disappears with zero animation.
   Opening stays instant (its own no-transition rule, same open-selector
   specificity trick as the animated path). */
@media ( prefers-reduced-motion: reduce ) and ( min-width: 601px ) {
    .ck-site-header .wp-block-navigation__submenu-container {
        transition: opacity 0s linear calc(var(--ck-menu-grace) + var(--ck-menu-anim)),
                    transform 0s linear calc(var(--ck-menu-grace) + var(--ck-menu-anim)),
                    visibility 0s linear calc(var(--ck-menu-grace) + var(--ck-menu-anim)) !important;
    }
    .ck-site-header .wp-block-navigation-item.has-child:hover > .wp-block-navigation__submenu-container,
    .ck-site-header .wp-block-navigation-item.has-child:has( > .wp-block-navigation-submenu__toggle[aria-expanded="true"] ) > .wp-block-navigation__submenu-container {
        transition: none !important;
    }
}

/* Footer — fat-footer link columns over a centred bottom bar. The Wind Spots
   column is the ck/site-links dynamic block (ck-site-buttons.php mu-plugin,
   driven by sites.json like the map + home buttons — one dashboard toggle
   governs all three public surfaces); Explore + Account are static markup in
   parts/footer.html. The dark-theme pairs are needed because the generic
   `body.dark-theme a/h2` rules further down otherwise outrank these. */
.ck-site-footer {
    background: var(--ck-header-bg);             /* match the header bar (Divi primary_nav_bg) */
    color: #ffffff;
    padding: 44px 5% 26px;
}
.ck-site-footer a {
    color: #ffffff;
}
.ck-footer-grid {
    display: grid;
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr);
    gap: 28px 48px;      /* between-group gap deliberately larger than the 24px inside the spots list */
    text-align: left;
}
/* The grid children are flow-layout blocks, so WP's block-gap emits
   margin-block-start on every non-first child — that knocked the Explore /
   Account headings ~24px below Wind Spots. The grid gap owns all spacing. */
.ck-site-footer .ck-footer-grid > * {
    margin-block-start: 0;
}
.ck-footer-heading,
body.dark-theme .ck-site-footer h2 {
    margin: 0 0 14px;
    padding-bottom: 10px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.14);  /* group rule (same hairline as the bottom bar) —
                                                            spans the whole column, so the 2-col spots list
                                                            reads as ONE group under its heading */
    font-size: 17px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: #ffffff;
}
.ck-footer-links {
    list-style: none;
    margin: 0;
    padding: 0;
}
.ck-footer-links li {
    margin: 0 0 8px;
    break-inside: avoid;      /* keep an item on one side of the 2-col spots list */
}
.ck-footer-links--spots {
    columns: 2;
    column-gap: 24px;
}
.ck-footer-links a,
#footer-info a,
body.dark-theme .ck-site-footer .ck-footer-links a {
    color: #d6d6d6;
    text-decoration: none;
}
@media (hover: hover) {
    .ck-footer-links a:hover,
    #footer-info a:hover,
    body.dark-theme .ck-site-footer .ck-footer-links a:hover {
        color: var(--wp--preset--color--sky);    /* same hover as the header nav */
    }
}
.ck-footer-bottom {
    margin-top: 36px;
    padding-top: 22px;
    border-top: 1px solid rgba(255, 255, 255, 0.14);
    text-align: center;
}
.ck-site-footer #footer-info {
    margin-top: 10px;
    font-size: 14px;
    color: #d6d6d6;
}
@media ( max-width: 780px ) {
    .ck-footer-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .ck-footer-nav--spots {
        grid-column: 1 / -1;  /* spots (2-col list) get their own row; Explore + Account share the next */
    }
    .ck-footer-links--spots {
        column-gap: 48px;     /* = the grid gap, so the right sub-column registers exactly with the
                                 second grid track (Account column) below it */
    }
}

/* ============================================================================
   Page template — every page's .ck-hero Cover carries its own title
   (templates/page.html renders no post-title block at all), and the hero sits
   flush under the sticky header (drop TT5's main top margin).
   ============================================================================ */
body:has(.ck-hero) main {
    margin-top: 0 !important;
}

/* ============================================================================
   Dark / light theme. body.dark-theme / body.light-theme are set by snippet 19's
   body_class filter (theme-agnostic — survives the flip). Only the generic
   selectors from the old CSS box are kept; the Divi-module ones (.et_pb_section,
   .et_pb_toggle, .et_pb_tabs, .et-boc, #page-container …) are dropped as dead.
   ============================================================================ */

body.dark-theme {
    background-color: #0f0f10;
    color: var(--ck-dark-text);
}
body.light-theme {
    background: #ffffff;
    color: #222;
}
body.dark-theme p,
body.dark-theme li,
body.dark-theme .entry-content {
    color: var(--ck-dark-text);
}
body.dark-theme h1,
body.dark-theme h2,
body.dark-theme h3,
body.dark-theme h4,
body.dark-theme h5,
body.dark-theme h6 {
    color: #cecece;
}
body.dark-theme a {
    color: #7db3f0;
}

/* ============================================================================
   Full-bleed layout — heroes, home bands, sticky footer.
   ============================================================================ */

/* Sticky footer: fill the viewport and push the footer to the bottom on short
   pages (replaces the old jQuery snippet 17). Flex column keeps the sticky
   header and the full-bleed hero working; margin-top:auto on the footer part
   does the pinning without stretching the content. overflow-x:clip is the
   safety net for any stray 100vw overflow (clip, not hidden, preserves the
   sticky header). */
.wp-site-blocks {
    overflow-x: clip;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100dvh;
}
.wp-site-blocks > footer {
    margin-top: auto;
}
/* Breathing room above the footer — content was ending flush against it on
   every page. Exception: a full-bleed band that ENDS the content (the home
   page) keeps its designed flush meeting edge with the footer. */
main {
    padding-bottom: 48px;
}
main:has(.entry-content > .ck-band:last-child) {
    padding-bottom: 0;
}

/* Full-bleed breakout, shared by the page-hero Covers (.ck-hero) and the
   home-page bands (.ck-band). Neither is align:full (the content was built
   under Divi, which had no alignfull), so they break out to the viewport edges
   with 100vw + centring margins instead. !important is required: the
   constrained parent layout applies `margin-inline: auto !important` to
   non-aligned children, which otherwise wins and leaves the 100vw box pinned to
   the padded content-left (~30px gap on the left / overflow on the right — on
   mobile that inflated the page width and pushed the hamburger off-screen). */
.ck-hero,
.ck-band {
    width: 100vw;
    max-width: 100vw;
    margin-left: calc( 50% - 50vw ) !important;
    margin-right: calc( 50% - 50vw ) !important;
}

/* The kiteometer alone matches its old custom Divi row: 95% of the viewport
   (capped like the 1080 container), breaking out of the constrained content.
   The margin's !important is LOAD-BEARING (post-flip fix, 2026-07-25): core's
   constrained-layout centering (.is-layout-constrained > :where(...)) sets
   margin-left: auto !important on every non-align* child, which silently
   killed this calc. On desktop nothing showed (the 1080 cap equals the
   container, so auto margins resolve to 0), but on phones the over-constrained
   auto margins dumped the whole 95vw excess on the RIGHT — the charts touched
   the screen edge. With the calc winning again the bleed is CENTRED: equal
   ~10px gutters at 390px. */
body:has(.ck-hero) #ck-echarts-root {
    width: min(95vw, 1080px);
    margin-left: calc(50% - min(47.5vw, 540px)) !important;
}
/* (The kiteometer toolbar's narrow-width wrap override that lived here was
   RETIRED post-flip 2026-07-25: the operator vetoed its wrap-and-centre snap
   at 480px, and the proper fix moved into the widget source itself
   (flex-wrap on .cke-toolbar; the pill's margin-left:auto right-aligns it on
   its own wrapped row) — the open-items debt note called exactly this. */

/* Divi fullwidth-header title parity: shadow + Divi's title sizes. The migrated
   hero titles carry a `has-large-font-size` preset (36px), and WordPress emits
   that preset class with `!important` — so it beat this rule and the hero H1
   rendered SMALLER than a plain content H2 (43px), inverting the hierarchy.
   `!important` here reclaims Divi's 50px so H1 is the largest heading again. */
.ck-hero .wp-block-heading {
    text-shadow: 0 0.05em 0.04em rgba(0, 0, 0, 0.4);
    font-size: 50px !important;
}
@media only screen and (max-width: 767px) {
    .ck-hero .wp-block-heading {
        font-size: 39px !important;
    }
}


/* ============================================================================
   .et_pb_button compat. Divi's theme supplied the base button styling, which
   dies at the flip — without it every CTA (tier messages, "Talk to us",
   "Ask a Question", site buttons) rendered as thin underlined links. Replicated
   from the Divi Customizer all_buttons_* settings (16px, #fff on #474747,
   radius 10, no icon, hover #282828). Component rules (.ck-site-buttons, the
   product CTA, the dark-theme hover) layer on top further down.
   ============================================================================ */
.et_pb_button,
.et_pb_button:visited {
    display: inline-block;
    padding: 0.3em 1em;
    font-size: 16px;
    font-weight: 500;
    line-height: 1.7em;
    color: #ffffff;
    background-color: var(--ck-btn-bg);
    border: 0;
    border-radius: 10px;
    text-decoration: none;
    letter-spacing: 0;
    cursor: pointer;
    transition: background-color 0.2s ease, color 0.2s ease;
}
@media (hover: hover) {
    .et_pb_button:hover {
        color: #ffffff;
        background-color: var(--ck-btn-bg-hover);
        text-decoration: none;
    }
}
.et_pb_button:focus-visible {
    color: #ffffff;
    background-color: var(--ck-btn-bg-hover);
    text-decoration: none;
}

/* ============================================================================
   Forecast + map embeds (Windguru / Windfinder / Windy / Marea / Google Map).
   Windguru renders as a centered block <div> (max-width 1080, margin auto), but
   the other widgets are inline <iframe>s, so they left-aligned at mismatched
   widths — the section looked misaligned. Make the iframes match Windguru:
   block-level, centered, capped to the same 1080 content width, even spacing.
   Targeted by the widgets' own ids so the CF7 Turnstile iframe is NOT affected.
   ============================================================================ */
.entry-content iframe#windyIframe,
.entry-content iframe#mareaIframe,
.entry-content iframe#googleMapsIframe,
.entry-content iframe[id^="wf-forecast"] {
    display: block !important;
    width: 100% !important;
    min-width: 0 !important;   /* Windfinder ships a min-width that blocks the cap */
    max-width: 1080px !important;
    /* Centre horizontally only. NB: do NOT add top/bottom margin here — the page
       already has even wp:spacer blocks between the embeds, so an extra vertical
       margin just compounds into uneven gaps. */
    margin-left: auto !important;
    margin-right: auto !important;
    margin-top: 0 !important;
    margin-bottom: 0 !important;
}
#windguru-widget-wrapper {
    margin-left: auto !important;
    margin-right: auto !important;
    margin-top: 0 !important;
    margin-bottom: 0 !important;
}
/* The Windguru iframe stays inline (unlike the others), so its line-box left a
   ~9px descender gap below it inside the wrapper — making the Windguru→Windfinder
   gap larger than the rest. Block it so the wrapper hugs the iframe. */
#windguru-widget-wrapper iframe {
    display: block !important;
    max-width: 100% !important;
}
/* Windfinder injects an empty placeholder <div> before its iframe; that div's
   block-gap margin added ~20px of space the other embeds don't have, so its gap
   looked bigger. Collapse the stray div so every embed gap matches. */
.entry-content div:has(+ script#wf_script) {
    display: none !important;
}
/* Windfinder's widget hard-codes the iframe to 479px, which was sized for its
   natural (wider) layout. Capping the width to 1080 reflows the table a little
   taller (its content box is ~494px incl. the sun/lat-lon footer row), so the
   default height clipped that last row. Pin it just above the measured content
   so nothing is cut, with a small buffer. */
.entry-content iframe[id^="wf-forecast"] {
    height: 505px !important;
}

/* ============================================================================
   Everything below is carried from the Divi Custom CSS box
   (cape-kiting-website/divi/custom.css) — theme-agnostic sections that survive
   the flip. Assembled by build note in DIVI_THEME_FLIP_RUNBOOK.md:
     custom.css lines 219-249  (button margins + dark-theme buttons)
     custom.css lines 303-731  (tier-message spacing, site notices, CF7,
                                Details FAQ, home page, WooCommerce notices,
                                Live-Weather product page)
   Values are unchanged from that source, with two kinds of later edits (2026-07-23
   review): repeated colour literals moved onto the :root tokens, and the
   product-page DARK-THEME selectors fixed (`.single-product`/`.woocommerce` are
   classes ON <body>, so `body.dark-theme .single-product …` never matched —
   chained selectors + !important where the light rule carries !important).
   `.entry-content` still works: the core post-content block emits both
   `entry-content` and `wp-block-post-content` classes.
   ============================================================================ */

/* --- custom.css 219-249: button margins + dark-theme buttons --- */
/* Apply margin around all buttons */
.wp-element-button,
.wp-block-button__link,
.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button {
    margin: 5px;   /* adjust spacing around buttons */
}

/* --- Dark Theme Buttons (minimal) --- */
/* Only set text color, background, and hover background */
body.dark-theme button,
body.dark-theme .button,
body.dark-theme .et_pb_button,
body.dark-theme .wp-element-button,
body.dark-theme .wp-block-button__link,
body.dark-theme input[type="button"],
body.dark-theme input[type="submit"] {
    color: #ffffff;
    background-color: var(--ck-btn-bg);
}

@media (hover: hover) {
    body.dark-theme button:hover,
    body.dark-theme .button:hover,
    body.dark-theme .et_pb_button:hover,
    body.dark-theme .wp-element-button:hover,
    body.dark-theme .wp-block-button__link:hover,
    body.dark-theme input[type="button"]:hover,
    body.dark-theme input[type="submit"]:hover {
        background-color: #6b6b6b;
    }
}

/* Tier-message spacing on block pages: the shortcode ships bare markup and
   relies on theme styles, but Divi's module margins only exist inside
   builder columns. Scoped to .entry-content so the Wind Map overlay's
   compact layout is untouched. */
.entry-content .ck-tier-message p {
    margin-bottom: 14px;
}
.entry-content .ck-tier-message .et_pb_button_module_wrapper {
    margin: 18px 0;
}

/* ============================================================================
   Site notices — [ck_site_notice]   (added 2026-07-19)
   Theme-aware colours for the per-site operational notices; ck-notices.php
   v1.1 emits no inline colour, these classes are the contract, and its SVG
   icons follow via currentColor. Site-wide, survives the theme flip.
   Base = dark-theme values (the server-rendered default), light overrides.
   ============================================================================ */

.ck-site-notice-icon {
    vertical-align: -3px;
    margin-right: 4px;
}

/* The theme-scoped selectors are required (not just the bare-class base): the
   generic `body.dark-theme p` colour rule above outweighs a lone class. The
   bare class doubles as the no-body-class default (= the dark values). */
.ck-site-notice--info,
body.dark-theme .ck-site-notice--info { color: #58b6ff; }
.ck-site-notice--warning,
body.dark-theme .ck-site-notice--warning { color: #ff9f43; }
.ck-site-notice--alert,
body.dark-theme .ck-site-notice--alert { color: #ff5252; }

body.light-theme .ck-site-notice--info { color: #1c6fc2; }
body.light-theme .ck-site-notice--warning { color: #b96a00; }
body.light-theme .ck-site-notice--alert { color: #d63031; }

/* ============================================================================
   Contact form — Contact Form 7   (added 2026-07-19)
   Layout + theme-aware inputs for the CF7 form that replaced the Divi
   Contact Form module when Contact Us went block (CF7 chosen for its
   stateless no-DB-storage behaviour). Survives the theme flip.
   ============================================================================ */

.wpcf7 {
    max-width: 720px;
    margin: 0 auto;
}
.wpcf7 form p {
    margin: 0 0 16px;
    padding: 0;
}
/* Paired fields (First/Last, Phone/Email) side by side on desktop, matching
   the old Divi half-width fields; stacked on phones. */
.wpcf7 .ck-cf-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 16px;
    row-gap: 16px;
    margin: 0 0 16px;
}
.wpcf7 .ck-cf-row p {
    margin: 0;
}
@media only screen and (max-width: 767px) {
    .wpcf7 .ck-cf-row {
        grid-template-columns: 1fr;
    }
}
.wpcf7 form label {
    display: block;
    font-weight: 600;
    margin-bottom: 0;
}
.wpcf7 input:not([type="submit"]),
.wpcf7 textarea {
    display: block;
    width: 100%;
    margin-top: 4px;
    padding: 10px 12px;
    border: 1px solid #bbb;
    border-radius: 4px;
    background: #ffffff;
    color: #222;
    font-size: 16px;
    box-sizing: border-box;
}
body.dark-theme .wpcf7 input:not([type="submit"]),
body.dark-theme .wpcf7 textarea {
    background: var(--ck-dark-panel-bg);
    color: var(--ck-dark-text);
    border-color: var(--ck-dark-field-border);
}
.wpcf7 input[type="submit"],
.wpcf7 .wpcf7-submit {
    display: block;
    margin: 18px 0 0 auto;
}
.wpcf7 .wpcf7-not-valid-tip {
    color: #ff5252;
}
body.light-theme .wpcf7 .wpcf7-not-valid-tip {
    color: #d63031;
}
.wpcf7 .wpcf7-response-output {
    text-align: center;
    border-radius: 4px;
}

/* --- Core Details block as FAQ accordion (Support page) — Divi-toggle look --- */
.entry-content .wp-block-details {
    padding: 20px 25px;
    margin-block-start: 0;
    margin-bottom: 20px;
    background-color: #f4f4f4;
    border: 1px solid #d9d9d9;
}
.entry-content .wp-block-columns:has(.wp-block-details) {
    row-gap: 0;
}
body.dark-theme .entry-content .wp-block-details {
    background-color: var(--ck-dark-panel-bg);
    border-color: var(--ck-dark-panel-border);
}
.entry-content .wp-block-details summary {
    list-style: none;
    cursor: pointer;
    /* Pull the summary out to the box edges (cancelling the box's 20/25 padding)
       and restore that padding on the summary itself — so the ENTIRE collapsed
       box is the clickable toggle, not just the inset question row. */
    margin: -20px -25px;
    padding: 20px 25px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    font-size: 16px;
    font-weight: 500;
}
.entry-content .wp-block-details summary::-webkit-details-marker {
    display: none;
}
.entry-content .wp-block-details summary::after {
    content: "+";
    font-size: 22px;
    font-weight: 400;
    line-height: 1;
    opacity: 0.65;
    flex: none;
}
.entry-content .wp-block-details[open] summary::after {
    content: "\2212";
}
.entry-content .wp-block-details[open] summary {
    /* When open, stop pulling the bottom edge and leave a small gap before the
       answer (top/side pull stays so the header still fills the box width). */
    margin-bottom: 0;
    padding-bottom: 12px;
}
.entry-content .wp-block-details p:last-child {
    margin-bottom: 0;
    padding-bottom: 0;
}

/* --- Home page block conversion: Airstrike font, full-bleed band, dynamic site buttons ---
   The @font-face is emitted by WordPress from theme.json (fontFamilies → Airstrike →
   fontFace, served from this theme's assets/fonts/), so there is no manual @font-face
   here and no dependency on the old Divi /uploads/et-fonts/ path. */
.ck-font-airstrike {
    font-family: var(--wp--preset--font-family--airstrike);
}
/* Home-page bands: the full-bleed breakout itself is shared with .ck-hero (see
   the full-bleed section above). margin-top:0 kills the block-gap that
   otherwise shows the dark body bg as a black line under the hero. */
.ck-band {
    margin-top: 0 !important;
    padding: 40px 0;
}
.ck-band > * {
    width: 80%;
    max-width: 1080px;
    margin-left: auto;
    margin-right: auto;
}
.ck-site-buttons {
    text-align: center;
}
body .ck-site-buttons .et_pb_button {
    display: inline-block;
    margin: 10px;
    padding-top: 5px;
    padding-bottom: 5px;
    font-size: 17px;
    color: #ffffff;
    border-width: 0;
}
body .ck-site-buttons--hero .et_pb_button {
    background-color: rgba(0,0,0,0.6);
}
body .ck-site-buttons--solid .et_pb_button {
    background-color: #232323;
    min-width: 150px;
    letter-spacing: 1px;
    text-align: center;
}
@media (hover: hover) {
    body .ck-site-buttons .et_pb_button:hover {
        background-color: rgba(0,0,0,0.86);
    }
}
@media only screen and (max-width: 980px) {
    .ck-site-buttons--hero {
        display: none;
    }
}
@media only screen and (min-width: 981px) {
    .ck-mobile-only {
        display: none;
    }
}
/* Home hero title at the original Divi sizes. !important is required to beat
   the `.ck-hero .wp-block-heading` 50px/39px !important rules (the home title
   is also a .wp-block-heading; equal specificity, so this later rule wins) —
   without it the title rendered 50px instead of Divi's 67px. */
.ck-hero .ck-hero-home-title {
    font-size: 67px !important;
}
@media only screen and (max-width: 767px) {
    .ck-hero .ck-hero-home-title {
        font-size: 41px !important;
    }
}
/* ck-hero cover parallax: parity with Divi, which ignored prefers-reduced-motion */
.ck-hero.has-parallax,
.ck-hero .wp-block-cover__image-background.has-parallax {
    background-attachment: fixed !important;
}
/* Touch devices: parallax off, matching Divi's et_mobile_device rule - a fixed
   background jumps when the mobile browser chrome collapses on scroll */
@media (hover: none) and (pointer: coarse) {
    .ck-hero.has-parallax,
    .ck-hero .wp-block-cover__image-background.has-parallax {
        background-attachment: scroll !important;
    }
}
/* Mobile: fit the home hero on the first screen - vh ignores the browser bar,
   svh does not; 80px = the fixed Divi mobile header (needs !important to beat
   the cover's inline min-height; scoped to the parallax hero so the 240px
   station/About heroes are unaffected) */
@media only screen and (max-width: 980px) {
    .ck-hero.has-parallax {
        min-height: calc(95vh - 80px) !important;
        min-height: calc(100svh - 80px) !important;
    }
}
/* Home hero subheading (Powered by Cape Kiting): same shadow as hero headings;
   original 15px phone size so it sits narrower than the title on mobile */
.ck-hero p.ck-font-airstrike {
    text-shadow: 0 0.05em 0.04em rgba(0,0,0,0.4);
}
@media only screen and (max-width: 767px) {
    .ck-hero p.ck-font-airstrike {
        font-size: 15px !important;
    }
}
/* WooCommerce info notices in the brand hero blue (Divi's default is a bright cyan
   that clashes with the site palette - first seen on the My Account subscriptions bar) */
.woocommerce-info,
.woocommerce-message.woocommerce-info,
p.woocommerce-Message--info {
    background-color: #e8f1f7 !important;
    color: #123c5a !important;
    border-left: 4px solid var(--wp--preset--color--deep-blue) !important;
    border-radius: 8px;
}
/* The callout's ACTION BUTTON is part of this component: WooCommerce drops
   e.g. "Browse products" inside the notice, and without component rules the
   generic body.dark-theme button styling repainted it as a dark blob flush
   against the pale bar (round 57, My Subscriptions). Deep-blue = the
   callout's own accent, identical in both themes because the callout itself
   is theme-invariant. !important matches the component's existing rules
   (WooCommerce's own .button styles load-order-race ours otherwise). */
.woocommerce-info .button,
.woocommerce-info .button:visited,
body.dark-theme .woocommerce-info .button {
    float: right;
    margin: -4px 0 0 16px;
    padding: 6px 14px;
    background-color: var(--wp--preset--color--deep-blue) !important;
    color: #ffffff !important;
    border: 0;
    border-radius: 8px;
    text-decoration: none;
}
@media (hover: hover) {
    .woocommerce-info .button:hover,
    body.dark-theme .woocommerce-info .button:hover {
        filter: brightness(1.25);
        background-color: var(--wp--preset--color--deep-blue) !important;
        color: #ffffff !important;
    }
}
/* WooCommerce notice BANNERS (wc-block-components-notice-banner — in a block
   theme WooCommerce renders even classic checkout/cart notices through this
   component). Its surfaces are hard-coded near-white (#f4fff7 / #f4f8ff), so
   in dark mode they sat as glowing white boxes (round 70). Follow the theme:
   dark surface + light text; the STATUS stays readable because the component
   keeps its hue on the 1px border and the icon. Light theme keeps WooCommerce
   defaults. !important: same load-order race as the classic notice rules. */
body.dark-theme .wc-block-components-notice-banner {
    background-color: #1e1e1e !important;
    color: #e6e6e6 !important;
}
body.dark-theme .wc-block-components-notice-banner a {
    color: var(--wp--preset--color--sky);
}
/* "Continue shopping" carries button classes; the component demotes such
   links to plain DARK text with !important (…__content .wc-forward
   { color:#2f2f2f !important }) — invisible on the dark surface. Match its
   selector + !important for dark theme only. */
body.dark-theme .wc-block-components-notice-banner > .wc-block-components-notice-banner__content .wc-forward {
    color: var(--wp--preset--color--sky) !important;
}
/* --- Live Weather product page (restyled 2026-07-21, retargeted 2026-07-23) ---
   Card/panel language matching the FAQ + account pages; brand blues; the
   Sign up button is the site's primary conversion CTA.
   NB the page renders through WooCommerce's BLOCKIFIED single-product template
   (`div.product` is a wp-block-group carrying woocommerce+product classes;
   there is NO `.summary`/`.product_meta` — the price/rating/category are
   `wp-block-woocommerce-product-*` BLOCKS). The 2026-07-21 rules were written
   against the classic template and three of them silently never matched;
   retargeted to the block classes 2026-07-23. */
.single-product .woocommerce-breadcrumb {
    display: none;
}
/* Category/meta block is irrelevant on a single-subscription shop — hide it
   (block class; classic .product_meta kept as a fallback). */
.single-product div.product .product_meta,
.single-product .wp-block-woocommerce-product-meta,
.single-product .woocommerce-product-gallery__trigger {
    display: none;
}
/* Gallery card: a SQUARE tile (aspect-ratio) capped well below its column so
   the summary text gets real breathing room; the icon centres inside it. */
.single-product div.product div.images {
    background: var(--ck-card-bg);
    border: 1px solid var(--ck-card-border);
    border-radius: 12px;
    padding: 20px;
    aspect-ratio: 1 / 1;
    max-width: 420px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.single-product div.product div.images .woocommerce-product-gallery__wrapper {
    width: 100%;
}
@media only screen and (max-width: 767px) {
    .single-product div.product div.images {
        max-width: 300px;
        float: none;
        margin-left: auto;
        margin-right: auto;
    }
}
/* NB `.single-product` is a class ON <body> — chain it (`body.dark-theme.single-product`),
   never nest it, or the dark rule silently never matches (2026-07-23 review fix). */
body.dark-theme.single-product div.product div.images {
    background: var(--ck-dark-panel-bg);
    border-color: var(--ck-dark-panel-border);
}
.single-product div.product .woocommerce-product-gallery img {
    max-width: 150px;
    margin: 0 auto;
    display: block;
}
.single-product .wp-block-woocommerce-product-rating a {
    color: var(--ck-text-muted);
    font-size: 14px;
}
/* the From range reads as fine print; the selected variation price is the hero
   number. The product-price BLOCK ships a has-large-font-size preset (36px,
   emitted with !important) — !important + higher specificity reclaims it. */
.single-product .wp-block-woocommerce-product-price {
    color: var(--ck-text-muted);
    font-size: 15px !important;
    font-weight: 400;
}
.woocommerce div.product .woocommerce-variation-price span.price {
    color: var(--ck-accent) !important;
    font-size: 32px !important;
    font-weight: 600 !important;
}
/* Location field: stacked label over a modern select */
.woocommerce div.product form.cart table.variations,
.woocommerce div.product form.cart table.variations tbody,
.woocommerce div.product form.cart table.variations tr,
.woocommerce div.product form.cart table.variations th,
.woocommerce div.product form.cart table.variations td {
    display: block;
    width: 100%;
    text-align: left;
    padding: 0;
    border: 0;
}
.woocommerce div.product form.cart table.variations th.label {
    padding-bottom: 6px;
    font-weight: 600;
}
.woocommerce div.product form.cart .variations select {
    -webkit-appearance: none !important;
    appearance: none !important;
    width: 100% !important;
    max-width: 340px;
    padding: 12px 42px 12px 14px !important;
    border: 1px solid #cfd8df !important;
    border-radius: 8px;
    font-size: 16px !important;
    color: #222 !important;
    background-color: #ffffff !important;
    background-image: url(data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='%23556677'%3E%3Cpath%20d='M7%2010l5%205%205-5z'/%3E%3C/svg%3E) !important;
    background-repeat: no-repeat !important;
    background-position: right 12px center !important;
    background-size: 18px !important;
}
/* Two traps here (2026-07-23 review fix — the select stayed white in dark
   theme): `.woocommerce` is a class ON <body> for single-product pages (no
   inner wrapper), so it must be CHAINED, and the light rule above carries
   !important (to outweigh WooCommerce's own select styling), so the dark
   override needs !important too or it loses regardless of specificity. */
body.dark-theme.woocommerce div.product form.cart .variations select {
    background-color: var(--ck-dark-panel-bg) !important;
    color: var(--ck-dark-text) !important;
    border-color: var(--ck-dark-field-border) !important;
}
/* --- Styled dropdown LIST (Chromium customizable select) --------------------
   The closed select is custom-styled above, but the OPENED list was raw native
   OS chrome (white panel, system font, blue highlight — reads decades out of
   date). `appearance: base-select` opts the picker into being a styleable
   top-layer element; browsers without support drop the unknown value and keep
   the native popup + all the styling above (progressive enhancement, no JS).
   The UA picker-icon is hidden because the select keeps its own SVG chevron. */
.woocommerce div.product form.cart .variations select,
.woocommerce div.product form.cart .variations select::picker(select) {
    appearance: base-select !important;
}
.woocommerce div.product form.cart .variations select::picker-icon {
    display: none;
}
.woocommerce div.product form.cart .variations select::picker(select) {
    background: #ffffff;
    border: 1px solid #cfd8df;
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
    padding: 6px;
    margin-top: 4px;
}
.woocommerce div.product form.cart .variations select option {
    padding: 10px 12px;
    border-radius: 6px;
    font-size: 16px;
    color: #222;
    cursor: pointer;
}
.woocommerce div.product form.cart .variations select option:hover,
.woocommerce div.product form.cart .variations select option:focus {
    background: #eaf3fa;
}
.woocommerce div.product form.cart .variations select option:checked {
    color: var(--ck-accent);
    font-weight: 600;
}
.woocommerce div.product form.cart .variations select option::checkmark {
    color: var(--ck-accent);
}
/* Dark picker — body.dark-theme.woocommerce chained (body-class trap, above). */
body.dark-theme.woocommerce div.product form.cart .variations select::picker(select) {
    background: var(--ck-dark-panel-bg);
    border-color: var(--ck-dark-field-border);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6);
}
body.dark-theme.woocommerce div.product form.cart .variations select option {
    color: var(--ck-dark-text);
    /* Explicit bg, not just text colour: Firefox's NATIVE popup (no base-select)
       partially honours option colours — light text alone could land on its
       default light popup. In Chromium this matches the picker bg (no-op). */
    background-color: var(--ck-dark-panel-bg);
}
body.dark-theme.woocommerce div.product form.cart .variations select option:hover,
body.dark-theme.woocommerce div.product form.cart .variations select option:focus {
    background: #2c2c2c;   /* matches the other dark hover bands */
}
/* No "Clear" link next to the Location dropdown — re-picking from the dropdown
   covers it. WC's JS shows/hides it with inline styles, hence !important. */
.woocommerce div.product form.cart .reset_variations {
    display: none !important;
}
/* The product "photo" is an icon, not a gallery: inert image. Zoom + lightbox
   theme supports are removed in functions.php; pointer-events neutralises the
   bare <a href="raw image file"> wrapper WC still renders around the img. */
.single-product div.product .woocommerce-product-gallery a,
.single-product div.product .woocommerce-product-gallery__image a {
    pointer-events: none;
    cursor: default;
}
/* --- No content-shift while the variation form boots (measured 2026-07-23) --
   1) WC injects the selected variation's price + description only after its
      JS runs, which pushed the Sign up button down 135px (desktop) / 186px
      (mobile) ~0.5s into the load. The .single_variation box exists
      server-side (empty), so reserve the populated height up front — the
      button starts at its final position, and switching to a location
      variation (shorter description) keeps the same reserved box, so the
      button never moves at all. Measured with the default Premium variation
      (the tallest description) at 1440 and 390 wide.
   2) The div.quantity box (sold-individually: only a hidden input + a
      screen-reader label inside) is floated with a 4px margin and collapsed
      late, nudging the button sideways — hide it whenever it contains no
      visible number input. */
.woocommerce div.product form.cart .single_variation {
    /* flow-root contains the description's bottom margin (it escaped by
       margin-collapse and left a 15px residual shift); min-height = the full
       measured populated extent (price 54 + description 51 + margins). */
    display: flow-root;
    min-height: 135px;
}
@media only screen and (max-width: 767px) {
    .woocommerce div.product form.cart .single_variation {
        min-height: 186px;   /* measured: the description wraps to 102px */
    }
}
.woocommerce div.product form.cart div.quantity:not(:has(input[type="number"])) {
    display: none;
}

/* the money button: the one gradient CTA on the site — brand blues only (the
   old blue-to-teal read as off-palette against the rest of the site) */
.woocommerce div.product form.cart .single_add_to_cart_button {
    background: linear-gradient(135deg, #006cd8, var(--ck-accent)) !important;
    color: #ffffff !important;
    border: 0 !important;
    border-radius: 8px !important;
    padding: 15px 46px !important;
    font-size: 18px !important;
    font-weight: 600 !important;
    letter-spacing: 0.3px;
    margin-top: 10px !important;
}
@media (hover: hover) {
    .woocommerce div.product form.cart .single_add_to_cart_button:hover {
        filter: brightness(1.1);
    }
}
/* reviews: no tab/panel chrome, section heading + cards, no placeholder avatars */
.single-product div.product .woocommerce-tabs,
.single-product .woocommerce-Tabs-panel {
    border: 0 !important;
    background: none !important;
    padding: 0 !important;
    box-shadow: none !important;
}
.single-product div.product .woocommerce-tabs {
    margin-top: 50px;
}
.single-product #reviews .commentlist {
    margin: 0 !important;
    padding: 0 !important;
    list-style: none !important;
}
.single-product .woocommerce-tabs ul.tabs {
    border: 0 !important;
    background: none !important;
    padding: 0 !important;
    margin: 0 0 30px !important;
}
.single-product .woocommerce-tabs ul.tabs::before,
.single-product .woocommerce-tabs ul.tabs li::before,
.single-product .woocommerce-tabs ul.tabs li::after {
    display: none !important;
}
.single-product .woocommerce-tabs ul.tabs li {
    background: none !important;
    border: 0 !important;
    border-radius: 0 !important;
    padding: 0 !important;
    margin: 0 !important;
    float: none !important;
    display: inline-block;
}
.single-product .woocommerce-tabs ul.tabs li a {
    font-family: var(--wp--preset--font-family--rajdhani);
    font-size: 28px;
    font-weight: 500;
    padding: 0 !important;
    color: inherit !important;
}
.single-product #reviews #comments > h2 {
    display: none;
}
.single-product #reviews .commentlist li img.avatar {
    display: none;
}
.single-product #reviews #comments ol.commentlist li .comment-text {
    margin: 0 !important;
    border: 1px solid var(--ck-card-border) !important;
    border-radius: 8px;
    background: var(--ck-card-bg);
    padding: 16px 20px !important;
}
/* body.dark-theme.single-product chained — see the div.images note above. */
body.dark-theme.single-product #reviews #comments ol.commentlist li .comment-text {
    background: var(--ck-dark-panel-bg);
    border-color: var(--ck-dark-panel-border) !important;
}
.single-product #reviews .commentlist li {
    margin-bottom: 14px;
}
.single-product #reviews .commentlist li p.meta {
    color: var(--ck-text-muted);
    font-size: 14px;
    margin-bottom: 8px;
}

/* ============================================================================
   WooCommerce dark theme — account / checkout / cart. Added 2026-07-23 when
   snippet 19's forced-light-on-Woo branch was removed, so the theme preference
   now applies on Woo pages too. Light theme keeps WooCommerce's stock look
   (the pre-existing state); these rules only restyle the dark side, on the
   same tokens as the rest of the site. NB `.woocommerce`/`.woocommerce-page`/
   `.single-product` are classes ON <body> — chain them, never nest (see the
   product-section note).
   ============================================================================ */

/* Form fields (address, checkout, coupon): same treatment as the CF7 dark
   inputs. .form-row is WooCommerce's field wrapper (a real descendant). */
body.dark-theme .form-row input.input-text,
body.dark-theme .form-row textarea,
body.dark-theme .form-row select {
    background-color: var(--ck-dark-panel-bg);
    color: var(--ck-dark-text);
    border-color: var(--ck-dark-field-border);
}
/* selectWoo (select2) renders the country/province selects as its own widgets;
   the dropdown panel is appended near <body>, so these are safe descendants. */
body.dark-theme .select2-container--default .select2-selection--single {
    background-color: var(--ck-dark-panel-bg);
    border-color: var(--ck-dark-field-border);
}
body.dark-theme .select2-container--default .select2-selection--single .select2-selection__rendered {
    color: var(--ck-dark-text);
}
body.dark-theme .select2-dropdown,
body.dark-theme .select2-search__field {
    background-color: var(--ck-dark-panel-bg);
    border-color: var(--ck-dark-field-border);
    color: var(--ck-dark-text);
}

/* Checkout payment section (the #payment panel + the per-gateway speech
   bubble). The Place order button is already covered by the dark button rules. */
body.dark-theme #payment,
body.dark-theme #payment div.payment_box {
    background-color: var(--ck-dark-panel-bg);
    color: var(--ck-dark-text);
}
body.dark-theme #payment div.payment_box::before {
    border-bottom-color: var(--ck-dark-panel-bg);   /* the bubble's arrow */
}

/* Order/account tables: WooCommerce's near-white borders vanish on the dark
   background — use the shared dark border. */
body.dark-theme table.shop_table,
body.dark-theme table.shop_table td,
body.dark-theme table.shop_table th {
    border-color: var(--ck-dark-panel-border);
}

/* YITH my-account navigation: its stock white cards glare on the dark page.
   YITH styles everything through CSS variables it defines on :root (inline
   style, values from its settings), so override the VARIABLES on body — a
   deeper definition wins for all descendants and beats YITH's #id-based
   selectors without any specificity fight. The blue hover/active accents
   (border + shadow) are deliberately left as YITH's own. */
/* Logout chip: YITH ships #aaa with white text — under 3:1 contrast in BOTH
   themes (round 57). Same variable mechanism; #666 clears WCAG AA on white. */
body {
    --ywcmap-logout-background-color: #666666;
    --ywcmap-logout-background-color-hover: #333333;
}
body.dark-theme {
    --ywcmap-items-text-color: var(--ck-dark-text);
    --ywcmap-items-text-color-hover: #ffffff;
    --ywcmap-items-text-color-active: #ffffff;
    --ywcmap-items-background-color: var(--ck-dark-panel-bg);
    --ywcmap-items-background-color-hover: #2c2c2c;   /* matches the mobile submenu band */
    --ywcmap-items-background-color-active: var(--ck-dark-panel-bg);
    --ywcmap-menu-background: var(--ck-dark-panel-bg);
    --ywcmap-menu-border-color: var(--ck-dark-panel-border);
    --ywcmap-items-border-color: var(--ck-dark-panel-border);
    --ywcmap-items-shadow-color: rgba(0, 0, 0, 0.4);
    /* Logout chip on the dark panel: quiet band tone, brand hover. */
    --ywcmap-logout-background-color: #2c2c2c;
    --ywcmap-logout-background-color-hover: var(--wp--preset--color--deep-blue);
}

/* ============================================================================
   Membership page — plan cards (.ck-plans = the wp:columns wrapper on
   /membership/). Three-card pricing comparison: Free / Single Spot / Premium
   (featured). Prices come LIVE from the store via [ck_plan_price]
   (mu-plugins/ck-plan-prices.php) — never hardcoded here or in the content.
   v2 (round 50): cards are flex columns so the CTAs sit on ONE baseline
   regardless of bullet count; the "Most popular" pill floats on the featured
   card's top border; name/price/per read as one stacked price block over a
   hairline divider. The dark-theme pairs outrank the generic body.dark-theme
   p/.et_pb_button rules, same trick as the footer section.
   ============================================================================ */
.ck-plans .ck-plan {
    position: relative;
    display: flex;
    flex-direction: column;
    height: 100%;                 /* equal-height cards across the row */
    box-sizing: border-box;
    padding: 30px 26px 28px;
    border: 1px solid rgba(0, 0, 0, 0.14);
    border-radius: 12px;
    background: #ffffff;
    text-align: center;
}
body.dark-theme .ck-plans .ck-plan {
    background: var(--ck-overlay-bg);
    border-color: rgba(255, 255, 255, 0.14);
}
.ck-plans .ck-plan--featured {
    border: 2px solid var(--ck-accent) !important;   /* wins over the dark pair's border-color */
    box-shadow: 0 8px 24px rgba(0, 108, 216, 0.22);
}
/* Centre-stage: the featured card sits in the MIDDLE column and reads slightly
   larger than its neighbours (the visual cue that also explains why the R79
   card sits out of ascending price order). Desktop only — a scaled full-width
   card looks off when the columns stack. */
@media ( min-width: 782px ) {
    .ck-plans .ck-plan--featured {
        transform: scale(1.04);
    }
}
/* The pill floats centred ON the featured card's top border — a badge, not a
   content row, so all three cards' plan names share one baseline. */
.ck-plan-flag,
body.dark-theme .ck-plan .ck-plan-flag {
    position: absolute;
    top: -13px;
    left: 50%;
    transform: translateX(-50%);
    margin: 0;
    padding: 3px 14px;
    border-radius: 13px;
    background: var(--ck-accent);
    color: #ffffff;
    font-family: Rajdhani, sans-serif;
    font-size: 13px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    white-space: nowrap;
}
.ck-plan h3 {
    margin: 0 0 4px;             /* the descriptor sits tight under the name */
    font-size: 19px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
/* Who the plan is for — answers "which plan is right for me" at a glance
   (round 55, pricing-page research). */
.ck-plan-desc,
body.dark-theme .ck-plan .ck-plan-desc {
    margin: 0 0 16px;
    font-size: 14.5px;
    opacity: 0.7;
}
.ck-plan-price,
body.dark-theme .ck-plan .ck-plan-price {
    margin: 0;
    font-family: Rajdhani, sans-serif;
    font-size: 48px;
    font-weight: 600;
    line-height: 1;
}
.ck-plan-price .woocommerce-Price-amount {
    font-size: inherit;           /* wc_price wraps the amount in its own spans */
    font-weight: inherit;
}
.ck-plan-per,
body.dark-theme .ck-plan .ck-plan-per {
    margin: 4px 0 0;
    font-size: 15px;
    opacity: 0.7;
}
/* "Everything in Free, plus" ladder line (paid cards) — carries the hairline
   when present; the Free card's list keeps its own. */
.ck-plan-ladder,
body.dark-theme .ck-plan .ck-plan-ladder {
    margin: 20px 0 0;
    padding: 16px 0 0;
    border-top: 1px solid rgba(128, 128, 128, 0.25);
    font-size: 14px;
    text-align: left;
    opacity: 0.75;
}
.ck-plan ul {
    list-style: none;
    margin: 20px 0 22px;
    padding: 16px 0 0;
    border-top: 1px solid rgba(128, 128, 128, 0.25);   /* hairline between price block and bullets */
}
.ck-plan .ck-plan-ladder + ul {
    margin-top: 10px;
    padding-top: 0;
    border-top: 0;
}
.ck-plan li {
    margin: 0 0 9px;
    padding-left: 26px;
    position: relative;
    text-align: left;              /* left-aligned check-list scans faster than centred lines */
    font-size: 16px;
    line-height: 1.45;
}
.ck-plan li::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0.28em;
    width: 15px;
    height: 15px;
    background: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23009ae8'%20stroke-width='3'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpolyline%20points='20%206%209%2017%204%2012'/%3E%3C/svg%3E") no-repeat center / contain;
}
/* Pin the CTA to the card bottom so all buttons share one baseline no matter
   how many bullet lines sit above them. */
.ck-plan .et_pb_button_module_wrapper {
    margin-top: auto;
    padding-top: 6px;
}
/* "What happens when I click": the risk-reversal microcopy under the CTA. */
.ck-plan-cancel,
body.dark-theme .ck-plan .ck-plan-cancel {
    margin: 8px 0 0;
    font-size: 13px;
    opacity: 0.65;
}
.ck-plan--featured .et_pb_button,
body.dark-theme .ck-plan--featured .et_pb_button {
    background: linear-gradient(135deg, #006cd8, var(--ck-accent));   /* the money-button gradient */
    color: #ffffff;
}
@media (hover: hover) {
    .ck-plan--featured .et_pb_button:hover,
    body.dark-theme .ck-plan--featured .et_pb_button:hover {
        filter: brightness(1.1);
    }
}
/* Stacked cards (mobile): breathing room so the floating pill of a following
   card never crowds the card above it. */
@media ( max-width: 781px ) {
    .ck-plans .wp-block-column + .wp-block-column {
        margin-top: 18px;
    }
}

/* ============================================================================
   Membership page — comparison table (.ck-compare wp:html, round 55). The
   detail layer under the plan cards (cards decide, the table verifies).
   Scrolls inside its own box on narrow screens; the page itself never
   scrolls horizontally. Premium column carried in the accent colour.
   ============================================================================ */
.ck-compare {
    overflow-x: auto;
}
.ck-compare table {
    border-collapse: collapse;
    margin: 0 auto;
    min-width: 640px;
}
.ck-compare th,
.ck-compare td {
    padding: 11px 20px;
    border-bottom: 1px solid rgba(128, 128, 128, 0.25);
    text-align: center;
    font-size: 16px;
}
.ck-compare tbody th {
    text-align: left;
    font-weight: 500;
}
.ck-compare thead th {
    font-family: Rajdhani, sans-serif;
    font-size: 17px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    border-bottom-width: 2px;
}
.ck-compare .ck-compare-featured {
    color: var(--ck-accent);
    font-weight: 600;
}
.ck-compare .woocommerce-Price-amount {
    font-size: inherit;
    font-weight: inherit;
}
