/**
 * Just Orthodontics — foundations.
 *
 * §01  Reset
 * §02  Document
 * §03  Typography
 * §04  Layout: containers and sections
 * §05  Prose
 * §06  Header
 * §07  Mobile navigation
 * §08  Footer
 * §09  Utilities
 *
 * Every colour, size, spacing and timing value comes from a custom property
 * emitted by the Builder's design-token layer (includes/design-system.php),
 * which reads the measured Figma values and the client's Theme Settings. No
 * brand value is written literally in this file.
 */

/* ═══ §01 Reset ═══════════════════════════════════════════════ */

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

html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
    /**
     * Anchored headings and in-page links come to rest below the sticky header
     * rather than under it. The offset already accounts for the WordPress
     * toolbar, so this is correct logged in as well as out.
     */
    scroll-padding-top: var(--jo-sticky-offset);
    scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
}

/**
 * The toolbar's real height, raised on the root element by the theme.
 *
 * It has to be declared here rather than on <body>: a custom property used
 * inside another custom property resolves in the scope the outer one was
 * declared in, and every sticky offset on the site is composed at :root.
 */
.jo-admin-bar { --jo-admin-bar: 32px; }
@media screen and (max-width: 782px) {
    .jo-admin-bar { --jo-admin-bar: 46px; }
}

/**
 * Below 600px WordPress stops pinning the toolbar and lets it scroll away with
 * the page. Anything still reserving room for it would then sit 46px too low
 * for the whole scroll, so the offset returns to zero at exactly the width
 * WordPress changes its mind.
 */
@media screen and (max-width: 600px) {
    .jo-admin-bar { --jo-admin-bar: 0px; }
}

body {
    margin: 0;
    background: var(--jo-white);
    color: var(--jo-body);
    font-family: var(--jo-font-body);
    font-size: var(--jo-body-size);
    line-height: var(--jo-body-lh);
    font-weight: 400;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    /* Nothing on this site is allowed to cause a sideways scroll. */
    overflow-x: clip;
}

h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd { margin: 0; }
ul, ol { margin: 0; padding: 0; }
li { list-style: none; }

img, picture, video, canvas, svg { display: block; max-width: 100%; }
img { height: auto; }

button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: 0; padding: 0; }

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

address { font-style: normal; }

/* ═══ §02 Document ════════════════════════════════════════════ */

/**
 * Focus.
 *
 * `:focus-visible` only, so a mouse click never draws a ring, but every
 * keyboard user gets an unmissable one. Two colours: the cream ring is for
 * anything sitting on navy or on a photograph, where the navy ring would
 * disappear.
 */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
    outline: 2px solid var(--jo-navy);
    outline-offset: 3px;
    border-radius: var(--jo-radius-focus);
}

.jo-section--navy :where(a, button):focus-visible,
.jo-hero :where(a, button):focus-visible,
.jo-tx-hero :where(a, button):focus-visible,
.jo-photo-cta :where(a, button):focus-visible,
.jo-footer :where(a, button):focus-visible,
.jo-header :where(a, button):focus-visible,
.jo-mnav :where(a, button):focus-visible {
    outline-color: var(--jo-cream);
}

.jo-skip {
    position: absolute;
    left: 50%;
    top: 0;
    transform: translate(-50%, -120%);
    z-index: 200;
    padding: 12px 22px;
    background: var(--jo-navy);
    color: var(--jo-cream);
    font-size: var(--jo-body-sm);
    font-weight: 600;
    border-radius: 0 0 var(--jo-radius-sm) var(--jo-radius-sm);
    transition: transform var(--jo-dur) var(--jo-ease);
}

.jo-skip:focus { transform: translate(-50%, 0); }

::selection {
    background: var(--jo-navy);
    color: var(--jo-cream);
}

.screen-reader-text {
    position: absolute !important;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* ═══ §03 Typography ══════════════════════════════════════════ */

/**
 * The display scale.
 *
 * Cormorant Garamond throughout, with the accent phrase in Bold Italic — the
 * house treatment the whole design is built on. The editor types the heading and
 * the phrase separately; `<em>` is generated, never typed.
 */
.jo-h1, .jo-h2, .jo-h3, .jo-h4,
.jo-hero__title, .jo-section-head__title {
    font-family: var(--jo-font-display);
    font-weight: 500;
    color: var(--jo-heading);
    text-wrap: balance;
}

.jo-h1 {
    font-size: var(--jo-h1);
    line-height: var(--jo-lh-h1);
    letter-spacing: var(--jo-tracking-h1);
    font-weight: 400;
}

.jo-h2 {
    font-size: var(--jo-h2);
    line-height: var(--jo-lh-h2);
    letter-spacing: var(--jo-tracking-h2);
}

.jo-h3 { font-size: var(--jo-h3); line-height: var(--jo-lh-h3); }
.jo-h4 { font-size: var(--jo-h4); line-height: var(--jo-lh-h4); }

/* The italic accent phrase inside any display heading. */
.jo-h1 em, .jo-h2 em, .jo-h3 em, .jo-h4 em,
.jo-hero__title em, .jo-section-head__title em,
.jo-cta-strip__title em, .jo-glass__title em {
    font-style: italic;
    font-weight: 700;
}

/* The italic sub-lead beneath a heading. */
.jo-pull {
    font-family: var(--jo-font-display);
    font-style: italic;
    font-weight: 700;
    font-size: var(--jo-h4);
    line-height: 1.3;
    color: var(--jo-muted);
    margin-top: var(--jo-space-3);
}

.jo-lead {
    font-size: var(--jo-body-lg);
    line-height: 1.7;
    color: var(--jo-muted);
}

/* Eyebrows: the pill, and the plain one used over photography. */
.jo-eyebrow,
.jo-eyebrow-pill span {
    font-family: var(--jo-font-body);
    font-size: var(--jo-eyebrow-size);
    line-height: var(--jo-eyebrow-lh);
    letter-spacing: var(--jo-eyebrow-tracking);
    font-weight: 500;
    text-transform: uppercase;
}

.jo-eyebrow {
    font-size: var(--jo-eyebrow-hero-size);
    letter-spacing: var(--jo-eyebrow-hero-tracking);
    color: var(--jo-cream);
}

.jo-eyebrow-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Its own size, so the pill cannot pick up the type scale of whatever
       block it happens to sit in. */
    font-size: var(--jo-eyebrow-size);
    min-height: 30px;
    padding: 5px 18px;
    border: 1px solid var(--jo-pill);
    border-radius: var(--jo-radius-pill);
    color: var(--jo-muted);
}

/* ═══ §04 Layout ══════════════════════════════════════════════ */

.jo-main { display: block; }

.jo-container {
    width: 100%;
    max-width: calc(var(--jo-container) + (var(--jo-gutter) * 2));
    margin-inline: auto;
    padding-inline: var(--jo-gutter);
}

/* Several card grids sit on a slightly narrower rail — part of the design's
   rhythm, not an inconsistency, so it is a container of its own. */
.jo-container--inner  { max-width: calc(var(--jo-container-inner) + (var(--jo-gutter) * 2)); }
.jo-container--narrow { max-width: calc(var(--jo-container-narrow) + (var(--jo-gutter) * 2)); }

/**
 * Section rhythm.
 *
 * A page is a sequence, not a stack of identical blocks, so a section resolves
 * its top and bottom independently. Both default to the ordinary content
 * value; a section that needs something else names it, and the name says what
 * kind of moment it is rather than how many pixels it wants.
 */
.jo-section {
    position: relative;
    --jo-sec-top: var(--jo-section-standard);
    --jo-sec-bottom: var(--jo-section-standard);
    padding-top: var(--jo-sec-top);
    padding-bottom: var(--jo-sec-bottom);
}

/* The scale, applied to both edges. */
.jo-section--space-flow     { --jo-sec-top: var(--jo-section-flow);      --jo-sec-bottom: var(--jo-section-flow); }
.jo-section--space-strip    { --jo-sec-top: var(--jo-section-strip);     --jo-sec-bottom: var(--jo-section-strip); }
.jo-section--space-band     { --jo-sec-top: var(--jo-section-band);      --jo-sec-bottom: var(--jo-section-band); }
.jo-section--space-snug     { --jo-sec-top: var(--jo-section-snug);      --jo-sec-bottom: var(--jo-section-snug); }
.jo-section--space-entry    { --jo-sec-top: var(--jo-section-entry);     --jo-sec-bottom: var(--jo-section-entry); }
.jo-section--space-standard { --jo-sec-top: var(--jo-section-standard);  --jo-sec-bottom: var(--jo-section-standard); }
.jo-section--space-feature  { --jo-sec-top: var(--jo-section-feature);   --jo-sec-bottom: var(--jo-section-feature); }

/* The same scale, one edge at a time — an entrance and an exit rarely match. */
.jo-section--top-flow     { --jo-sec-top: var(--jo-section-flow); }
.jo-section--top-strip    { --jo-sec-top: var(--jo-section-strip); }
.jo-section--top-band     { --jo-sec-top: var(--jo-section-band); }
.jo-section--top-snug     { --jo-sec-top: var(--jo-section-snug); }
.jo-section--top-entry    { --jo-sec-top: var(--jo-section-entry); }
.jo-section--top-standard { --jo-sec-top: var(--jo-section-standard); }
.jo-section--top-feature  { --jo-sec-top: var(--jo-section-feature); }

.jo-section--bottom-flow     { --jo-sec-bottom: var(--jo-section-flow); }
.jo-section--bottom-strip    { --jo-sec-bottom: var(--jo-section-strip); }
.jo-section--bottom-band     { --jo-sec-bottom: var(--jo-section-band); }
.jo-section--bottom-snug     { --jo-sec-bottom: var(--jo-section-snug); }
.jo-section--bottom-entry    { --jo-sec-bottom: var(--jo-section-entry); }
.jo-section--bottom-standard { --jo-sec-bottom: var(--jo-section-standard); }
.jo-section--bottom-feature  { --jo-sec-bottom: var(--jo-section-feature); }

.jo-section--flush { --jo-sec-top: 0px; --jo-sec-bottom: 0px; }

/**
 * A run of sections on one ground is one band.
 *
 * Figma does not draw Finding us, the patient journey and the opening hours as
 * three padded sections — it draws them as three rows 32px apart inside a
 * single body frame. Rendering them as separate sections was putting a full
 * bottom padding and a full top padding between each pair, which is where the
 * 161px of empty white came from.
 *
 * So a section that declares it continues the one above gives that one's
 * bottom padding away and supplies the single gap itself. The run keeps the
 * entrance of its first section and the exit of its last, and the blocks
 * between them are spaced once rather than twice.
 *
 * It is declared per section rather than inferred from the ground, because two
 * white sections in a row are usually two separate frames that Figma spaces
 * normally — About's two split panels sit 120px apart, not 32. The renderer
 * marks the follower; `:has()` lets the one before it respond without needing
 * to know what page it is on.
 */
.jo-section:has(+ .jo-section--flows) { --jo-sec-bottom: 0px; }

/**
 * Section grounds.
 *
 * White is the page. A section only takes a ground when the frame gives it one,
 * which is why `white` exists as an explicit modifier as well as being the
 * default — a section that needs to state "yes, white, on purpose" can.
 *
 * The warm band is `--jo-band` (#FEFCF7 in the frame), not the card surface and
 * not the brand cream. It used to be called `--cream` and to draw the card
 * surface, which is warmer, and it was being asked for by roughly twice as many
 * sections as the design gives it to. Both were why the site read beige.
 */
.jo-section--band  { background: var(--jo-band); }
.jo-section--white { background: var(--jo-white); }

.jo-section--navy {
    background: var(--jo-navy);
    color: var(--jo-cream);
}

.jo-section--navy .jo-h2,
.jo-section--navy .jo-h3,
.jo-section--navy .jo-h4 { color: var(--jo-cream); }

/* Consecutive sections sharing a ground are handled by the run model above,
   which now covers white as well — white is the ground most of the site is on,
   and it was the one case the old adjacent-sibling rules could not see. */

/* The shared section opener. */
.jo-section-head { margin-bottom: clamp(32px, 3.2vw, 56px); }

.jo-section-head--centre {
    text-align: center;
    max-width: 760px;
    margin-inline: auto;
}

.jo-section-head--centre .jo-eyebrow-pill { margin-bottom: var(--jo-space-4); }

.jo-section-head--left { max-width: 900px; }
.jo-section-head--left .jo-eyebrow-pill { margin-bottom: var(--jo-space-4); }

.jo-section-head__title { margin-bottom: var(--jo-space-3); }

.jo-section-head__intro {
    color: var(--jo-soft);
    max-width: 62ch;
}

.jo-section-head--centre .jo-section-head__intro { margin-inline: auto; }

.jo-section--navy .jo-section-head__intro { color: var(--jo-on-navy); }

/* ═══ §05 Prose ═══════════════════════════════════════════════ */

/**
 * Editor-written copy.
 *
 * Deliberately narrow in scope: the fields an editor fills are rich text, and
 * this is the one place their markup is styled. Everything else on the site is
 * a component with its own rules.
 */
.jo-prose { color: var(--jo-body); }

.jo-prose > * + * { margin-top: 1.15em; }

.jo-prose p { margin: 0; }

.jo-prose strong { font-weight: 700; color: var(--jo-heading); }
.jo-prose em { font-style: italic; }

.jo-prose a {
    color: var(--jo-navy);
    text-decoration: underline;
    text-underline-offset: 3px;
    text-decoration-thickness: 1px;
    transition: color var(--jo-dur-fast) var(--jo-ease);
}

.jo-prose a:hover { color: var(--jo-navy-deep); }

.jo-prose h2, .jo-prose h3, .jo-prose h4 {
    font-family: var(--jo-font-display);
    color: var(--jo-heading);
    font-weight: 500;
    margin-top: 1.6em;
}

.jo-prose h2 { font-size: var(--jo-h3); line-height: var(--jo-lh-h3); }
.jo-prose h3 { font-size: var(--jo-h4); line-height: var(--jo-lh-h4); }
.jo-prose h4 { font-size: var(--jo-h5); }

.jo-prose ul, .jo-prose ol { padding-left: 1.3em; }
.jo-prose li { list-style: disc; margin-bottom: .5em; }
.jo-prose ol li { list-style: decimal; }

.jo-prose blockquote {
    padding-left: var(--jo-space-5);
    border-left: 2px solid var(--jo-border);
    font-family: var(--jo-font-display);
    font-style: italic;
    font-size: var(--jo-h4);
    color: var(--jo-muted);
}

.jo-prose--narrow { max-width: 68ch; margin-inline: auto; }

.jo-empty-msg,
.jo-build-note {
    color: var(--jo-soft);
    text-align: center;
    padding-block: var(--jo-space-7);
}

.jo-build-note {
    border: 1px dashed var(--jo-border);
    border-radius: var(--jo-radius-md);
    background: var(--jo-surface);
    color: var(--jo-muted);
    padding: var(--jo-space-5);
}

/* ═══ §06 Header ══════════════════════════════════════════════ */

/**
 * One header, two presentations.
 *
 * Over a photographic hero it is transparent, with a utility strip above it and
 * the links in their own translucent pill. Once scrolled — and from the top on
 * any page with no photograph behind it — the whole row becomes a single navy
 * glass pill inset from the page edge.
 *
 * The second presentation is byte-for-byte the same on every page. An article
 * page simply starts in it.
 */
.jo-header {
    position: fixed;
    top: var(--jo-admin-bar);
    left: 0;
    right: 0;
    z-index: 100;
    /* The frame leaves air above the utility line rather than starting the
       header hard against the top of the window. */
    padding-top: var(--jo-header-top);
    transition: transform var(--jo-dur) var(--jo-ease);
}

/* The sticky pill supplies its own inset, so the resting offset comes off. */
.jo-header.is-stuck { padding-top: 0; }

.jo-header__util {
    height: var(--jo-util-height);
    display: flex;
    /* Figma sets this line at the foot of its band rather than centred in it,
       which keeps it clear of the very top of the window. */
    align-items: flex-end;
    justify-content: center;
    padding-inline: var(--jo-gutter);
    padding-bottom: 2px;
    color: var(--jo-cream);
    font-size: var(--jo-body-sm);
    opacity: .92;
    transition: opacity var(--jo-dur) var(--jo-ease),
                height var(--jo-dur) var(--jo-ease),
                transform var(--jo-dur) var(--jo-ease);
}

.jo-header__util-inner {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    justify-content: center;
    text-align: center;
}

.jo-header__util-sep { opacity: .5; }

.jo-header__bar {
    height: var(--jo-nav-height);
    transition: height var(--jo-dur) var(--jo-ease),
                margin var(--jo-dur) var(--jo-ease),
                background-color var(--jo-dur) var(--jo-ease),
                box-shadow var(--jo-dur) var(--jo-ease),
                border-radius var(--jo-dur) var(--jo-ease);
}

.jo-header__inner {
    height: 100%;
    max-width: calc(var(--jo-container) + (var(--jo-gutter) * 2));
    margin-inline: auto;
    /*
     * Asymmetric on purpose. The logo sits on the page gutter like everything
     * else, but the call to action is placed where the sticky pill will put it,
     * so that it stays exactly where it is when the header sticks. Matching the
     * gutter on this side would look tidier in isolation and make the button
     * jump on the first scroll.
     */
    padding-left: var(--jo-gutter);
    padding-right: calc(var(--jo-sticky-inset) + var(--jo-sticky-pad));
    /*
     * Three columns with equal outer tracks, so the navigation is centred on the
     * header rather than on whatever space the logo and the button happen to
     * leave. Flex would push it off-centre by half the difference between them,
     * and that difference changes with the length of the button's label.
     */
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: var(--jo-space-5);
}

.jo-header__logo { justify-self: start; }
.jo-header__actions { justify-self: end; }

/* ── Logo ─────────────────────────────────────────────────── */

.jo-header__logo {
    flex: 0 0 auto;
    display: block;
    width: var(--jo-logo-width);
    transition: width var(--jo-dur) var(--jo-ease);
}

.jo-header__logo-img { width: 100%; height: auto; }

.jo-header__logo-text {
    font-family: var(--jo-font-display);
    font-size: var(--jo-h5);
    color: var(--jo-cream);
    white-space: nowrap;
}

/* ── Navigation ───────────────────────────────────────────── */

.jo-header__nav {
    flex: 1 1 auto;
    display: flex;
    justify-content: center;
    min-width: 0;
}

.jo-nav {
    display: flex;
    align-items: center;
    gap: var(--jo-nav-gap);
    /* Figma: a 74px pill around 41px items — 16px of breathing room each side. */
    padding: clamp(6px, 0.93vw, 16px);
    border-radius: var(--jo-radius-pill);
    background: var(--jo-nav-pill-bg);
    -webkit-backdrop-filter: var(--jo-nav-pill-blur);
    backdrop-filter: var(--jo-nav-pill-blur);
    transition: background-color var(--jo-dur) var(--jo-ease),
                backdrop-filter var(--jo-dur) var(--jo-ease),
                padding var(--jo-dur) var(--jo-ease);
}

.jo-nav__item { position: relative; }

.jo-nav__link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    /* Figma: a 41px pill. Set outright rather than left to the sum of padding
       and line-height, which drifts with the font's own metrics. */
    min-height: var(--jo-nav-item-height);
    padding: var(--jo-nav-item-pad-y) var(--jo-nav-item-pad-x);
    border-radius: var(--jo-radius-pill);
    color: var(--jo-sticky-text);
    font-size: var(--jo-nav-item-size);
    line-height: 1.2;
    white-space: nowrap;
    transition: background-color var(--jo-dur-fast) var(--jo-ease),
                color var(--jo-dur-fast) var(--jo-ease);
}

.jo-nav__link:hover { background: var(--jo-nav-item-hover); }

.jo-nav__item.is-current > .jo-nav__link {
    background: var(--jo-nav-item-active);
    color: var(--jo-nav-item-active-fg);
    font-weight: 700;
}

.jo-nav__chevron {
    width: .7em;
    height: .7em;
    transition: transform var(--jo-dur-fast) var(--jo-ease);
}

.jo-nav__item[data-mega].is-open .jo-nav__chevron { transform: rotate(180deg); }

.jo-nav__empty {
    color: var(--jo-cream);
    font-size: var(--jo-body-sm);
    opacity: .7;
}

/**
 * A button carrying two wordings.
 *
 * Both spans are in the anchor; only one is ever shown. The anchor's own
 * aria-label supplies the accessible name, so what a screen reader announces
 * does not change with the viewport.
 */
.jo-btn--has-compact .jo-btn__label-compact { display: none; }

/* ── Actions ──────────────────────────────────────────────── */

.jo-header__actions {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: var(--jo-space-3);
}

.jo-burger {
    display: none;
    align-items: center;
    gap: 9px;
    padding: 10px 14px;
    border-radius: var(--jo-radius-pill);
    border: 1px solid rgba(244, 239, 230, .4);
    color: var(--jo-cream);
    font-size: var(--jo-body-sm);
    font-weight: 600;
    letter-spacing: .02em;
    transition: background-color var(--jo-dur-fast) var(--jo-ease);
}

.jo-burger:hover { background: rgba(250, 250, 250, .12); }

.jo-burger__box {
    display: grid;
    gap: 4px;
    width: 18px;
}

.jo-burger__line {
    display: block;
    height: 1.5px;
    background: currentColor;
    border-radius: 2px;
    transition: transform var(--jo-dur) var(--jo-ease),
                opacity var(--jo-dur-fast) var(--jo-ease);
}

/* ── The navy glass state ─────────────────────────────────── */

/**
 * `.is-stuck` is added by the scroll module; `.jo-header--dark` is set from the
 * server on pages with no hero. Both resolve to exactly the same rules, so the
 * bar a reader meets while scrolling is identical everywhere.
 */
.jo-header.is-stuck .jo-header__util,
.jo-header--dark .jo-header__util {
    height: 0;
    opacity: 0;
    overflow: hidden;
    transform: translateY(-8px);
    pointer-events: none;
}

.jo-header.is-stuck .jo-header__bar,
.jo-header--dark .jo-header__bar {
    height: var(--jo-nav-height-stuck);
    margin: var(--jo-sticky-top) var(--jo-sticky-inset) 0;
    border-radius: var(--jo-radius-pill);
    background: var(--jo-sticky-bg);
    -webkit-backdrop-filter: var(--jo-sticky-blur);
    backdrop-filter: var(--jo-sticky-blur);
    border: 1px solid var(--jo-sticky-border);
    box-shadow: var(--jo-sticky-highlight), var(--jo-sticky-shadow);
}

.jo-header.is-stuck .jo-header__inner,
.jo-header--dark .jo-header__inner {
    padding-left: var(--jo-sticky-pad-start);
    padding-right: var(--jo-sticky-pad);
    max-width: none;
}

.jo-header.is-stuck .jo-header__logo,
.jo-header--dark .jo-header__logo { width: var(--jo-logo-width-stuck); }

/* The nav loses its own pill: the whole bar is now the pill. */
.jo-header.is-stuck .jo-nav,
.jo-header--dark .jo-nav {
    background: transparent;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    padding: 0;
}

.jo-header.is-stuck .jo-nav__item.is-current > .jo-nav__link,
.jo-header--dark .jo-nav__item.is-current > .jo-nav__link {
    background: var(--jo-nav-item-active);
    color: var(--jo-sticky-active-fg);
}

/**
 * The header hides itself when the reader scrolls down and returns the moment
 * they scroll up — the bar is only in the way when they are moving away from it.
 * Never applied at the top of the page, and never while the mobile menu is open.
 */
.jo-header.is-hidden { transform: translateY(calc(-100% - var(--jo-sticky-top))); }

/* ── Spacing beneath a solid header ───────────────────────── */

/**
 * A page with a hero has the header drawn over the photograph, so nothing has to
 * make room for it. Every other page does.
 */
body:not(.jo-has-hero) .jo-main {
    padding-top: calc(var(--jo-nav-height-stuck) + var(--jo-sticky-top) + clamp(24px, 3vw, 56px));
}

/* ═══ §07 Mobile navigation ═══════════════════════════════════ */

/**
 * Full width, not a drawer.
 *
 * On a phone the menu is the whole screen and is composed as its own page: a
 * large lockup, generous spacing, the treatments, the booking action, and the
 * practice's real contact details — which is what most people opening a menu on
 * a phone are actually after.
 */
.jo-mnav {
    position: fixed;
    inset: 0;
    z-index: 150;
    background: var(--jo-navy);
    overflow-y: auto;
    overscroll-behavior: contain;

    /* Entrance timing, kept together so the whole sequence can be read at once. */
    --jo-mnav-in: .36s;      /* how long one element takes to arrive */
    --jo-mnav-out: .16s;     /* leaving is quicker than arriving */
    --jo-mnav-rise: 14px;
}

.jo-mnav[hidden] { display: none; }

/**
 * ── Opening ──────────────────────────────────────────────────────
 *
 * The panel used to be shown by dropping the `hidden` attribute, which is an
 * instant swap from nothing to a full navy screen. It now arrives: the ground
 * fades up, then the contents rise into it a few at a time.
 *
 * `hidden` still does the real work — it is what keeps the panel out of the
 * document when closed — but it is now removed a frame before the transition
 * starts and restored after the exit finishes, so the state the attribute
 * describes and the state the visitor sees stay in step. Everything between
 * those two moments is `.is-open`.
 */
.jo-mnav {
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--jo-mnav-out) var(--jo-ease);
}

.jo-mnav.is-open {
    opacity: 1;
    pointer-events: auto;
    transition-duration: .28s;
}

/*
 * The three groups that rise: the header row, each primary link, and each of
 * the blocks under them. Their resting state is the *closed* state, so the exit
 * needs no rules of its own — it simply runs this transition, which is shorter
 * and carries no delay.
 */
.jo-mnav__head,
.jo-mnav__nav > ul > li,
.jo-mnav__body > :not(.jo-mnav__nav) {
    opacity: 0;
    transform: translateY(var(--jo-mnav-rise));
    transition: opacity var(--jo-mnav-out) var(--jo-ease),
                transform var(--jo-mnav-out) var(--jo-ease);
}

.jo-mnav.is-open .jo-mnav__head,
.jo-mnav.is-open .jo-mnav__nav > ul > li,
.jo-mnav.is-open .jo-mnav__body > :not(.jo-mnav__nav) {
    opacity: 1;
    transform: none;
    transition: opacity var(--jo-mnav-in) var(--jo-ease) var(--jo-mnav-delay, 0ms),
                transform var(--jo-mnav-in) var(--jo-ease) var(--jo-mnav-delay, 0ms);
}

/*
 * The stagger, written out rather than computed: the menu has a known and
 * fairly short list, and an explicit ladder is easier to read — and to retime —
 * than an index threaded through the markup. Anything past the end of a ladder
 * simply shares its last step, so a longer menu still arrives in order.
 */
.jo-mnav.is-open .jo-mnav__head { --jo-mnav-delay:  50ms; }

.jo-mnav.is-open .jo-mnav__nav > ul > li:nth-child(1)    { --jo-mnav-delay:  90ms; }
.jo-mnav.is-open .jo-mnav__nav > ul > li:nth-child(2)    { --jo-mnav-delay: 122ms; }
.jo-mnav.is-open .jo-mnav__nav > ul > li:nth-child(3)    { --jo-mnav-delay: 154ms; }
.jo-mnav.is-open .jo-mnav__nav > ul > li:nth-child(4)    { --jo-mnav-delay: 186ms; }
.jo-mnav.is-open .jo-mnav__nav > ul > li:nth-child(5)    { --jo-mnav-delay: 218ms; }
.jo-mnav.is-open .jo-mnav__nav > ul > li:nth-child(n+6)  { --jo-mnav-delay: 250ms; }

.jo-mnav.is-open .jo-mnav__body > :not(.jo-mnav__nav):nth-child(2)   { --jo-mnav-delay: 210ms; }
.jo-mnav.is-open .jo-mnav__body > :not(.jo-mnav__nav):nth-child(3)   { --jo-mnav-delay: 240ms; }
.jo-mnav.is-open .jo-mnav__body > :not(.jo-mnav__nav):nth-child(4)   { --jo-mnav-delay: 270ms; }
.jo-mnav.is-open .jo-mnav__body > :not(.jo-mnav__nav):nth-child(5)   { --jo-mnav-delay: 300ms; }
.jo-mnav.is-open .jo-mnav__body > :not(.jo-mnav__nav):nth-child(n+6) { --jo-mnav-delay: 330ms; }

.jo-mnav__panel {
    min-height: 100%;
    display: flex;
    flex-direction: column;
    padding: var(--jo-gutter);
    padding-top: calc(var(--jo-admin-bar) + var(--jo-gutter));
}

.jo-mnav__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--jo-space-4);
    padding-bottom: var(--jo-space-6);
    border-bottom: 1px solid var(--jo-line-on-navy);
}

.jo-mnav__logo { display: block; width: clamp(140px, 38vw, 190px); }
.jo-mnav__logo-img { width: 100%; height: auto; }

.jo-mnav__logo-text {
    font-family: var(--jo-font-display);
    font-size: var(--jo-h4);
    color: var(--jo-cream);
}

.jo-mnav__close {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px;
    border: 1px solid rgba(244, 239, 230, .4);
    border-radius: var(--jo-radius-pill);
    color: var(--jo-cream);
    font-size: var(--jo-body-sm);
    font-weight: 600;
}

.jo-mnav__body {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    gap: var(--jo-space-7);
    padding-block: var(--jo-space-7);
}

.jo-mnav__nav a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--jo-space-4);
    padding: 14px 0;
    border-bottom: 1px solid var(--jo-line-on-navy);
    font-family: var(--jo-font-display);
    font-size: clamp(26px, 6.5vw, 34px);
    line-height: 1.2;
    color: var(--jo-cream);
    transition: color var(--jo-dur-fast) var(--jo-ease),
                padding-left var(--jo-dur) var(--jo-ease);
}

.jo-mnav__nav a:hover { padding-left: 8px; }
.jo-mnav__nav .is-current a { font-style: italic; }

.jo-mnav__arrow {
    flex: 0 0 auto;
    width: .6em;
    height: .6em;
    opacity: .55;
}

.jo-mnav__group-title,
.jo-footer__col-title {
    font-size: var(--jo-label-size);
    letter-spacing: var(--jo-label-tracking);
    text-transform: uppercase;
    font-weight: 500;
    color: var(--jo-on-navy);
    margin-bottom: var(--jo-space-4);
}

.jo-mnav__sub {
    display: grid;
    gap: 10px;
}

.jo-mnav__sub a {
    color: rgba(244, 239, 230, .82);
    font-size: var(--jo-body-lg);
    transition: color var(--jo-dur-fast) var(--jo-ease);
}

.jo-mnav__sub a:hover { color: var(--jo-cream); }

.jo-mnav__action .jo-btn { width: 100%; }

.jo-mnav__contact {
    display: grid;
    gap: var(--jo-space-3);
}

.jo-mnav__contact-link {
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--jo-cream);
    font-size: var(--jo-body-lg);
}

.jo-mnav__contact-link .jo-icon { color: var(--jo-on-navy); flex: 0 0 auto; }
.jo-mnav__address { align-items: flex-start; }
.jo-mnav__address .jo-icon { margin-top: .35em; }

.jo-social--mnav { justify-content: flex-start; }

/* ═══ §08 Footer ══════════════════════════════════════════════ */

.jo-footer {
    background: var(--jo-footer);
    color: var(--jo-on-navy);
    padding-block: clamp(48px, 5vw, 76px) clamp(24px, 2.4vw, 34px);
    font-size: var(--jo-body-sm);
}

/**
 * The footer's four columns.
 *
 * The tracks are proportions with no floor. Minimum track sizes here used to add
 * up to more than the container could give them between roughly 820 and 900
 * pixels, and a grid whose minimums do not fit does not wrap — it overflows, and
 * takes the page's horizontal scrollbar with it. The proportions shrink instead,
 * and the columns stack below 900 where they would otherwise get too narrow to
 * read.
 */
.jo-footer__top {
    display: grid;
    grid-template-columns: minmax(0, 1.4fr) repeat(2, minmax(0, 1fr)) minmax(0, 1.3fr);
    gap: clamp(28px, 3vw, 56px);
    padding-bottom: clamp(36px, 4vw, 60px);
}

.jo-footer__logo { display: block; width: clamp(120px, 12vw, 150px); margin-bottom: var(--jo-space-5); }
.jo-footer__logo-img { width: 100%; height: auto; }

.jo-footer__logo-text {
    font-family: var(--jo-font-display);
    font-size: var(--jo-h4);
    color: var(--jo-cream);
}

.jo-footer__address {
    display: grid;
    gap: 2px;
    line-height: 1.6;
    margin-bottom: var(--jo-space-5);
}

.jo-footer__contact { margin-bottom: var(--jo-space-4); }

.jo-footer__contact-label {
    display: block;
    font-weight: 600;
    color: var(--jo-on-navy);
    margin-bottom: 2px;
}

.jo-footer__contact-value {
    color: var(--jo-cream);
    transition: opacity var(--jo-dur-fast) var(--jo-ease);
}

.jo-footer__contact-value:hover { opacity: .75; }

.jo-footer__col ul { display: grid; gap: 9px; }

.jo-footer__col a {
    color: rgba(244, 239, 230, .8);
    transition: color var(--jo-dur-fast) var(--jo-ease);
}

.jo-footer__col a:hover { color: var(--jo-cream); }

.jo-footer__col-title--social { margin-top: var(--jo-space-6); }

.jo-footer__disclaimer {
    border: 1px solid var(--jo-line-on-navy);
    border-radius: var(--jo-radius-sm);
    padding: clamp(14px, 1.4vw, 20px) clamp(16px, 1.8vw, 26px);
    line-height: 1.55;
    margin-bottom: clamp(20px, 2vw, 30px);
}

.jo-footer__bottom {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--jo-space-5);
    flex-wrap: wrap;
}

.jo-footer__legal ul {
    display: flex;
    flex-wrap: wrap;
    gap: var(--jo-space-5);
}

.jo-footer__legal a {
    color: rgba(244, 239, 230, .8);
    transition: color var(--jo-dur-fast) var(--jo-ease);
}

.jo-footer__legal a:hover { color: var(--jo-cream); }

/* ═══ §09 Utilities ═══════════════════════════════════════════ */

.jo-icon {
    flex: 0 0 auto;
    fill: currentColor;
    vertical-align: -0.125em;
}

.jo-social {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
}

.jo-social__link {
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    border: 1px solid var(--jo-line-on-navy);
    color: var(--jo-cream);
    transition: background-color var(--jo-dur-fast) var(--jo-ease),
                border-color var(--jo-dur-fast) var(--jo-ease);
}

.jo-social__link:hover {
    background: rgba(244, 239, 230, .12);
    border-color: rgba(244, 239, 230, .4);
}

.jo-phone, .jo-email {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.jo-pagination {
    display: flex;
    justify-content: center;
    gap: var(--jo-space-3);
    margin-top: var(--jo-space-8);
}

.jo-pagination .page-numbers {
    display: grid;
    place-items: center;
    min-width: 40px;
    height: 40px;
    padding-inline: 10px;
    border: 1px solid var(--jo-border);
    border-radius: var(--jo-radius-pill);
    color: var(--jo-body);
    transition: background-color var(--jo-dur-fast) var(--jo-ease),
                color var(--jo-dur-fast) var(--jo-ease);
}

.jo-pagination .page-numbers:hover,
.jo-pagination .page-numbers.current {
    background: var(--jo-navy);
    border-color: var(--jo-navy);
    color: var(--jo-cream);
}

.jo-404 { text-align: center; }
.jo-404 .jo-eyebrow-pill { margin-bottom: var(--jo-space-4); }
.jo-404 .jo-lead { margin: var(--jo-space-4) auto 0; max-width: 56ch; }

.jo-404__links {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--jo-space-3);
    margin-top: var(--jo-space-7);
}

.jo-search-results {
    display: grid;
    gap: 2px;
    margin-top: var(--jo-space-7);
}

.jo-search-results a {
    display: block;
    padding: var(--jo-space-5);
    border-radius: var(--jo-radius-md);
    transition: background-color var(--jo-dur-fast) var(--jo-ease);
}

.jo-search-results a:hover { background: var(--jo-surface); }

.jo-search-results__title {
    display: block;
    font-family: var(--jo-font-display);
    font-size: var(--jo-h4);
    color: var(--jo-heading);
}

.jo-search-results__meta {
    display: block;
    margin-top: 4px;
    color: var(--jo-soft);
}

/* ═══ Responsive ══════════════════════════════════════════════ */

/**
 * The navigation collapses on available room, not on a device category: the
 * links, the lockup and the booking button stop fitting comfortably somewhere
 * around 1100px, and that is where the burger takes over.
 */
@media (max-width: 1100px) {
    .jo-header__nav { display: none; }
    .jo-burger { display: inline-flex; }
    .jo-header__actions { margin-left: auto; }
}

/* The footer stacks before its columns get too narrow to read, which happens
   higher up than the point at which the header sheds its utility line. */
@media (max-width: 900px) {
    .jo-footer__top {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: var(--jo-space-7) var(--jo-space-6);
    }
    .jo-footer__brand { grid-column: 1 / -1; }
    .jo-footer__col--right { grid-column: 1 / -1; }
}

@media (max-width: 820px) {
    .jo-header__util { display: none; }
}

/**
 * The phone header: lockup, booking button, menu.
 *
 * The button used to be dropped here, which left the bar — and especially the
 * sticky bar, where it is the only thing on screen — with a lockup at one end
 * and a burger at the other and nothing in between. It stays now, and the room
 * for it comes from its own padding rather than from the logo or the tap
 * target either side of it.
 *
 * The grid also stops being three tracks with a centred middle: with the
 * navigation gone there is nothing to centre, and an empty middle track would
 * push the button and the burger apart.
 */
@media (max-width: 1100px) {
    .jo-header__inner {
        grid-template-columns: auto 1fr auto;
        gap: var(--jo-space-4);
    }

    .jo-header__actions {
        grid-column: 3;
        gap: var(--jo-space-3);
    }

    .jo-header__cta {
        --jo-btn-pad-x: 18px;
        white-space: nowrap;
    }
}

/*
 * The menu control drops its word here rather than at 560.
 *
 * Measured across the range, the full booking wording needs about 240px of
 * clear space and has it everywhere except a narrow band just above 560 —
 * where the viewport has tightened but the burger is still carrying "Menu".
 * Shedding that word a little earlier removes the band, and the full wording
 * then survives continuously down to the point below where it genuinely
 * stops fitting.
 */
@media (max-width: 620px) {
    .jo-burger__label { display: none; }

    /*
     * Icon-only, but not a small target: 44px square is the minimum comfortable
     * tap area, and it also squares the control up against the 46px booking
     * button beside it rather than leaving a short pill next to a tall one.
     */
    .jo-burger {
        padding: 0;
        min-width: 44px;
        min-height: 44px;
        justify-content: center;
    }
}

/*
 * Below this the full wording no longer clears the lockup and the menu, so the
 * short wording from Theme Settings takes over. Measured, not assumed: at 560
 * the button has ~50px of slack and at 500 it has none.
 */
@media (max-width: 560px) {
    .jo-btn--has-compact .jo-btn__label-full    { display: none; }
    .jo-btn--has-compact .jo-btn__label-compact { display: inline; }

    .jo-header__cta { --jo-btn-pad-x: 16px; }
}

@media (max-width: 560px) {
    .jo-footer__top { grid-template-columns: minmax(0, 1fr); }
    .jo-footer__bottom { justify-content: flex-start; }
}
