/* Variable font: one file covers the whole 300–700 weight range we use
   (400/600/700). Neither family ships a real italic face here — the two
   italic uses (.front-cinematic__script, .svc-cards__note) get a browser-
   synthesized oblique, which is fine for small decorative/note text. */
@font-face {
    font-family: "Quicksand";
    font-style: normal;
    font-weight: 300 700;
    font-display: swap;
    src: url("../fonts/quicksand-latin-var.woff2") format("woff2");
}

:root {
    /* Neutrals. */
    --color-black: #000000;
    --color-near-black: #0f0f0f;
    --color-white: #ffffff;

    /*
     * Brand — sampled from the client logo
     * (design/pinellasdentalspecialties-logo.webp), which is built from exactly
     * three colours: the tooth mark's cyan #00a8e1, the "PINELLAS" wordmark's
     * deeper azure #2890cd, and the implant screw / "DENTAL SPECIALTIES"
     * graphite #535353. Everything else in the theme reads the semantic roles
     * below, never these hexes directly — swap them for a new project and the
     * whole site follows.
     *
     * Relationship to midcountydental.com (the sister general-dentistry site):
     * the cyan accent family is deliberately SHARED — it is what makes the two
     * sites read as one practice group when a patient follows a cross-link. The
     * difference is the dark anchor: Mid County is built on navy (#1f305e),
     * this site on graphite. Cyan-on-graphite reads clinical and specialist;
     * cyan-on-navy reads family practice. Keep that split — do not drift this
     * palette back toward navy, and do not re-tune the cyan away from theirs.
     *
     * Contrast (WCAG 2.1 AA), all measured, all at or above the values they
     * replace: --color-bg-inverse is 12.69:1 on white — safe as text anywhere.
     * --color-accent is 3.07:1 on white / 4.13:1 on --color-bg-inverse: use it
     * for borders, icons and fills only (3:1 floor), never for text on white.
     * It is the logo cyan darkened 2.5% — the brightest form of that colour
     * that still clears the 3:1 floor. --color-accent-dark (5.53:1 on white,
     * 4.51:1 on --color-bg-muted-dark) carries the wordmark's azure hue and is
     * the AA-safe variant for text/links/hover on every light surface, doubling
     * as a solid fill behind white button text. --color-accent-light (7.60:1 on
     * --color-bg-inverse) is the AA-safe variant for text/links/icons on the
     * dark background.
     */
    --color-bg: var(--color-white);
    --color-text: var(--color-near-black);
    --color-bg-inverse: #2b343a;
    --color-text-inverse: var(--color-white);
    --color-accent: #009ed4;
    --color-accent-dark: #0e6ea6;
    --color-accent-light: #7fd4f0;

    /* Quiet cool tints for panels that need to lift off the white page
       without becoming a coloured band (section grounds, menu columns).
       Tinted toward the graphite anchor rather than navy, so they sit under
       the dark surfaces without a blue cast. */
    /* Third-level text — a label under something that already has a colour,
       where both --color-text and --color-accent-dark would compete with what
       is above it. Desaturated from the graphite anchor: 5.89:1 on white,
       5.38:1 on --color-bg-muted, so it is AA as body text on either ground. */
    --color-text-muted: #5b666d;
    --color-bg-muted: #f2f5f7;
    --color-bg-muted-dark: #e3e9ed;

     --color-error: #c0392b;
    --color-error-bg: #fdecea;

    /* Typography — Lora for headings, Quicksand for everything else. */
    --font-heading: "Quicksand", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    --font-body: "Quicksand", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

    /* Layout. */
    --wrapper-width: 1350px;
    --wrapper-header: 1500px;
    --wrapper-text-width: 900px;
    --wrapper-gutter: 20px;
}

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

html {
    font-size: 18px;
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    background: var(--color-bg);
    color: var(--color-text);
    font-family: var(--font-body);
    font-size: 1em;
    font-weight: 400;
    line-height: 1.6;
    overflow-wrap: break-word;
    -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
h4,
h5,
h6 {
    margin: 0 0 0.5em;
    font-family: var(--font-heading);
    font-weight: 700;
    font-synthesis: weight;
    line-height: 1.1;
}

h1 {
    font-size: clamp(34px, 5vw, 60px);
}

h2 {
    font-size: clamp(28px, 4vw, 44px);
}

h3 {
    font-size: clamp(22px, 3vw, 32px);
}

h4 {
    font-size: clamp(20px, 2vw, 24px);
}

p,
ul,
ol {
    margin: 0 0 1em;
    font-weight: 500;
}

a {
    color: inherit;
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
    outline: 3px solid var(--color-accent-dark);
    outline-offset: 2px;
}

img,
svg,
video,
iframe {
    max-width: 100%;
}

img,
video {
    height: auto;
}

figure {
    margin: 0;
}

/* Accessibility primitives. */

.screen-reader-text {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.skip-link {
    position: absolute;
    top: -100px;
    left: 0;
    z-index: 100000;
    padding: 12px 20px;
    background: var(--color-black);
    color: var(--color-white);
}

.skip-link:focus {
    position: fixed;
    top: 0;
    width: auto;
    height: auto;
    margin: 0;
    overflow: visible;
    clip-path: none;
}

/*
 * Global reduced-motion floor. Individual components already tune their own
 * motion, but this catch-all guarantees that anything added later — including
 * JS-driven transitions (drawer submenu height, slider smooth-scroll) — is
 * neutralised when the visitor asks for less motion. Kept last so it wins.
 */
@media (prefers-reduced-motion: reduce) {

    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/*
 * Button system. `.btn` is the base; `.primary` / `.secondary` / `.outline` are
 * combinable modifiers (e.g. `.btn.secondary.outline`). Each variant only
 * reassigns the local --btn-* properties.
 *
 * No border-radius by design — the brand is sharp and clinical.
 */

.btn {
    --btn-bg: var(--color-bg-inverse);
    --btn-color: var(--color-white);
    --btn-border: var(--color-bg-inverse);
    --btn-bg-hover: var(--color-accent);
    --btn-color-hover: var(--color-text);
    --btn-border-hover: var(--color-accent);

    display: inline-block;
    padding: 0.75em 1.375em;
    border: 1px solid var(--btn-border);
    border-radius: 3px;
    background: var(--btn-bg);
    color: var(--btn-color);
    font-family: var(--font-body);
    font-size: 15px;
    font-weight: 700;
    letter-spacing: 0.12em;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    text-transform: uppercase;
    cursor: pointer;
    transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.btn:hover,
.btn:focus-visible {
    background: var(--btn-bg-hover);
    border-color: var(--btn-border-hover);
    color: var(--btn-color-hover);
}

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

.btn.secondary {
    --btn-bg: var(--color-white);
    --btn-color: var(--color-bg-inverse);
    --btn-border: var(--color-white);
    --btn-bg-hover: var(--color-accent);
    --btn-color-hover: var(--color-text);
    --btn-border-hover: var(--color-accent);
}

/* Transparent fill, inheriting the variant's colour as the border and text. */
.btn.outline {
    --btn-bg: transparent;
    --btn-color: var(--color-bg-inverse);
    --btn-border: currentcolor;
    --btn-bg-hover: var(--color-bg-inverse);
    --btn-color-hover: var(--color-white);
    --btn-border-hover: var(--color-bg-inverse);
}

.btn.secondary.outline {
    --btn-color: var(--color-white);
    --btn-bg-hover: var(--color-white);
    --btn-color-hover: var(--color-bg-inverse);
    --btn-border-hover: var(--color-white);
}

.btn.primary.outline {
    --btn-color: var(--color-accent);
    --btn-bg-hover: var(--color-accent);
    --btn-color-hover: var(--color-text);
    --btn-border-hover: var(--color-accent);
}

@media (prefers-reduced-motion: reduce) {
    .btn {
        transition: none;
    }
}

/*
 * Inline SVG icons (see inc/icons.php). Sized in em so an icon scales with the
 * text next to it, and coloured via currentColor so it inherits the surrounding
 * text colour. Set width/height on the icon call, or font-size on a parent, to
 * resize.
 */
.icon {
    display: inline-block;
    width: 1em;
    height: 1em;
    fill: currentcolor;
    vertical-align: -0.125em;
}

/*
 * Image placeholder — the [responsive_image] fallback shown until a real
 * attachment is set. Deliberately loud (dashed border, striped ground) so an
 * un-swapped image can't be missed before launch.
 */
.image-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    aspect-ratio: 3 / 2;
    padding: 20px;
    border: 2px dashed var(--color-accent-dark);
    background: repeating-linear-gradient(45deg, var(--color-bg-muted), var(--color-bg-muted) 12px, var(--color-bg-muted-dark) 12px, var(--color-bg-muted-dark) 24px);
    text-align: center;
}

.image-placeholder--square {
    aspect-ratio: 1 / 1;
}

.image-placeholder--wide {
    aspect-ratio: 16 / 9;
}

.image-placeholder--portrait {
    aspect-ratio: 3 / 4;
}

/* Media wrappers routinely set line-height: 0 to kill the inline-image
   descender gap; this label is real text inside one, so it restates its own. */
.image-placeholder__label {
    max-width: 90%;
    line-height: 1.4;
    font-family: var(--font-body);
    font-size: 14px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--color-text);
}

.image-placeholder__label::before {
    content: "▢ replace image";
    display: block;
    margin-bottom: 6px;
    font-size: 11px;
    letter-spacing: 0.14em;
    color: var(--color-accent-dark);
}

/* Article and page content chrome. */

.content-wrapper {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 40px;
    width: 100%;
    max-width: var(--wrapper-width);
    margin: 0 auto;
    padding: 48px var(--wrapper-gutter);
}

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

.site-main,
.widget-area {
    min-width: 0;
}

.entry-title {
    margin: 0 0 1rem;
}


.post-thumbnail img,
.entry-content img,
.entry-content iframe,
.entry-content video,
.entry-content embed,
.entry-content object {
    display: block;
    max-width: 100%;
    height: auto;
}

.post-navigation,
.pagination {
    display: flex;
    gap: 16px;
    margin-top: 32px;
}

.post-navigation {
    justify-content: space-between;
}

@media (min-width: 1025px) {
    .content-wrapper:has(.widget-area) {
        grid-template-columns: minmax(0, 1fr) 300px;
    }
}


/*#region Header*/
/*
 * Site header.
 *
 * Mobile-first. Base styles are the tablet/mobile layout (centred wordmark + a
 * four-tab action bar, with off-canvas drawers); the desktop top bar and nav row
 * switch on at 1024px. Drawers are position:fixed and slide in with a transform,
 * so they overlay the page rather than pushing it, above a dimmed backdrop.
 */

.site-header {
    position: sticky;
    top: 0;
    /* Above page content, below the drawers/backdrop (z-index 900+) so an open
       menu still covers it. */
    z-index: 500;
    background: var(--color-white);
    color: var(--color-text);
    transition: transform 0.3s ease;
}

/* Auto-hide: slid up out of view while scrolling down (main.js toggles this);
   any scroll up brings it back. */
.site-header--hidden {
    transform: translateY(-100%);
}

/* -------------------------------------------------------------------------- *
 * Top bar (desktop only)
 * -------------------------------------------------------------------------- */

.site-topbar {
    display: none;
}

.site-topbar__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    width: 100%;
    max-width: var(--wrapper-header);
    margin: 0 auto;
    padding: 10px var(--wrapper-gutter);
    font-size: 1em;
}

.site-topbar__item {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--color-white);
    text-decoration: none;
}

/* Address sits left, Call Us right. margin-left rather than relying on the
   inner's space-between, so the phone still hugs the right edge on a site that
   has no Address saved and therefore only renders this one item. */
.site-topbar__item[href^="tel"] {
    flex: 0 0 auto;
    margin-left: auto;
}

.site-topbar__item:hover,
.site-topbar__item:focus-visible {
    color: var(--color-accent-light);
}

.site-topbar__item .icon {
    width: 16px;
    height: 16px;
    flex: 0 0 auto;
    color: var(--color-accent-light);
}

/* -------------------------------------------------------------------------- *
 * Main header row: logo | menu | booking CTA
 * -------------------------------------------------------------------------- */

/*
 * Mobile: only the logo lives here (menu and CTA are hidden), so a plain
 * centred block is all that's needed. The grid that lays out all three cells
 * starts at the desktop breakpoint further down.
 */
.site-header__main {
    width: 100%;
    max-width: var(--wrapper-header);
    margin: 0 auto;
    padding: 0 var(--wrapper-gutter);
}

.site-branding {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 14px 0;
}

/* Desktop-only — on mobile the .header-tabs bar already carries Call / Book. */
.site-header__cta {
    display: none;
}

.site-branding .custom-logo-link {
    display: inline-block;
}

.site-branding .custom-logo {
    height: auto;
    max-height: 64px;
    width: auto;
}

.site-title {
    margin: 0;
    font-family: var(--font-heading);
    font-size: 30px;
}

.site-title a {
    color: var(--color-bg-inverse);
    text-decoration: none;
}

/* -------------------------------------------------------------------------- *
 * Desktop nav row (desktop only)
 * -------------------------------------------------------------------------- */

.site-nav {
    display: none;
}

.primary-navigation__menu {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 28px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.primary-navigation__menu a {
    display: inline-block;
    color: var(--color-text);
    font-family: var(--font-body);
    font-size: 15px;
    letter-spacing: 0.1em;
    text-decoration: none;
    text-transform: uppercase;
    font-weight: 700;
}

.primary-navigation__menu a:hover,
.primary-navigation__menu a:focus-visible {
    color: var(--color-accent-dark);
}

/* Reserved on every top-level link, not just the active one, so switching page
   moves the bar instead of nudging the whole row down. */
.primary-navigation__menu>li>a {
    padding-bottom: 2px;
    border-bottom: 2px solid transparent;
}

/* Dropdowns. */
.primary-navigation__menu .menu-item-has-children {
    position: relative;
}

.primary-navigation__menu .sub-menu {
    position: absolute;
    top: 100%;
    left: 0;
    z-index: 50;
    display: none;
    min-width: 220px;
    margin: 0;
    padding: 8px 0;
    background: var(--color-white);
    border-top: 2px solid var(--color-accent);
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
    list-style: none;
}

.primary-navigation__menu .menu-item-has-children:hover>.sub-menu,
.primary-navigation__menu .menu-item-has-children:focus-within>.sub-menu {
    display: block;
}

.primary-navigation__menu .sub-menu li {
    display: block;
}

.primary-navigation__menu .sub-menu a {
    position: relative;
    display: block;
    padding: 10px 20px;
    color: var(--color-text);
    font-size: 16px;
    letter-spacing: 0.04em;
    text-transform: none;
}

/* Zebra striping: alternate rows are faintly greyed. */
.primary-navigation__menu .sub-menu li:nth-child(even)>a {
    background-color: rgba(0, 0, 0, 0.04);
}

/* Hover keeps the text colour and grows an underline from the left. */
.primary-navigation__menu .sub-menu a::after {
    position: absolute;
    right: 20px;
    bottom: 6px;
    left: 20px;
    height: 1px;
    background: currentcolor;
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.25s ease;
    content: "";
}

.primary-navigation__menu .sub-menu a:hover,
.primary-navigation__menu .sub-menu a:focus-visible {
    color: var(--color-text);
}

.primary-navigation__menu .sub-menu a:hover::after,
.primary-navigation__menu .sub-menu a:focus-visible::after {
    transform: scaleX(1);
}

/* Third-level (nested) submenus cascade to the right by default, so a stray
   3-level branch is never broken. The mega menu below overrides this. */
.primary-navigation__menu .sub-menu .sub-menu {
    top: 0;
    left: 100%;
}

/* -------------------------------------------------------------------------- *
 * Mega menu (3 levels) — the Dental Services item only.
 * Give that menu item the CSS class "nav-mega" (Appearance → Menus → CSS
 * Classes). Its level-2 children become column headings and each one's level-3
 * children render as a static list, all inside one wide panel. Two-level
 * submenus elsewhere are unaffected.
 * -------------------------------------------------------------------------- */

/* Containing-block fallback for submenu panels. */
.primary-navigation {
    position: relative;
}

.primary-navigation__menu .nav-mega {
    position: relative;
}

/* Panel is only as wide as its columns (max-content), capped so 3 columns
   never overflow the viewport. Each level-2 child becomes one column; with a
   single column the panel is one column wide, not the full row. */
.primary-navigation__menu .nav-mega>.sub-menu {
    left: 0;
    width: max-content;
    max-width: min(94vw, 940px);
    padding: 0;
    grid-auto-flow: column;
    grid-auto-columns: minmax(200px, max-content);
}

.primary-navigation__menu .nav-mega:hover>.sub-menu,
.primary-navigation__menu .nav-mega:focus-within>.sub-menu {
    display: grid;
}

/* Columns. The middle one is tinted, like the design. */
.primary-navigation__menu .nav-mega>.sub-menu>li {
    padding: 22px 8px 26px;
}

.primary-navigation__menu .nav-mega>.sub-menu>li:nth-child(even) {
    background: var(--color-bg-muted);
}

/* Column heading = the level-2 link. */
.primary-navigation__menu .nav-mega>.sub-menu>li>a {
    padding: 0 18px 10px;
    font-family: var(--font-heading);
    font-size: 22px;
    letter-spacing: 0;
}

.primary-navigation__menu .nav-mega>.sub-menu>li>a::after {
    display: none;
}

/* Level-3 list: static (not a flyout), plain — no panel chrome. */
.primary-navigation__menu .nav-mega .sub-menu .sub-menu {
    position: static;
    display: block;
    min-width: 0;
    padding: 0;
    background: none;
    border-top: 0;
    box-shadow: none;
}

.primary-navigation__menu .nav-mega .sub-menu .sub-menu a {
    padding: 7px 18px;
}

/* No zebra inside the mega — the tinted middle column carries the rhythm. */
.primary-navigation__menu .nav-mega .sub-menu li:nth-child(even)>a {
    background: none;
}

/* -------------------------------------------------------------------------- *
 * Dropdown affordance (chevron) + active-page highlight
 * -------------------------------------------------------------------------- */

/* A down chevron after every TOP-LEVEL item that opens a dropdown, so the
   affordance is visible without hovering. Direct children only (>), so the mega
   menu's level-2 column headings and nested submenu parents never get one.
   It flips to point up while the panel is open.

   Drawn as a square with two borders rotated 45deg rather than a glyph: it
   inherits the link's colour, scales with font-size (em units), and doesn't
   depend on a font shipping the character. */
.primary-navigation__menu>.menu-item-has-children>a {
    display: inline-flex;
    align-items: center;
}

.primary-navigation__menu>.menu-item-has-children>a::after {
    content: "";
    width: 0.4em;
    height: 0.4em;
    margin-left: 0.55em;
    border-right: 2px solid var(--color-accent);
    border-bottom: 2px solid var(--color-accent);
    /* Nudge up so the rotated square optically centres on the text baseline. */
    transform: translateY(-0.12em) rotate(45deg);
    transition: transform 0.2s ease, border-color 0.2s ease;
}

.primary-navigation__menu>.menu-item-has-children:hover>a::after,
.primary-navigation__menu>.menu-item-has-children:focus-within>a::after {
    transform: translateY(0.06em) rotate(-135deg);
    border-color: var(--color-accent-dark);
}

/*
 * Active page, marked at every level it appears on.
 *
 * Three class families have to be covered. WordPress adds current-menu-* to an
 * item that links to the page being viewed, and both current-page-* and
 * current_page_* to an item whose target page is an ancestor of it. Those two
 * are what let a page that is not in the menu at all still light up its
 * section — and on such a page current-page-ancestor can be the ONLY class
 * present, so omitting it silently breaks exactly that case.
 *
 * The selectors use descendant combinators deliberately: with a third-level
 * page open, its level-2 parent carries current-menu-parent and its level-1
 * grandparent carries current-menu-ancestor, and all three rows should read as
 * active, not just the deepest one.
 */
.primary-navigation__menu .current-menu-item>a,
.primary-navigation__menu .current-menu-parent>a,
.primary-navigation__menu .current-menu-ancestor>a,
.primary-navigation__menu .current-page-parent>a,
.primary-navigation__menu .current-page-ancestor>a,
.primary-navigation__menu .current_page_item>a,
.primary-navigation__menu .current_page_parent>a,
.primary-navigation__menu .current_page_ancestor>a {
    color: var(--color-bg-inverse);
}

/* Navy on near-black is far too close to read as a state change on its own, so
   the top row carries a bar as well. It is --color-accent-dark rather than the
   base accent: 5.18:1 on white against the 3:1 floor for a non-text marker, and
   it stays distinct from hover, which only recolours the text. */
.primary-navigation__menu>.current-menu-item>a,
.primary-navigation__menu>.current-menu-parent>a,
.primary-navigation__menu>.current-menu-ancestor>a,
.primary-navigation__menu>.current-page-parent>a,
.primary-navigation__menu>.current-page-ancestor>a,
.primary-navigation__menu>.current_page_item>a,
.primary-navigation__menu>.current_page_parent>a,
.primary-navigation__menu>.current_page_ancestor>a {
    border-bottom-color: var(--color-accent);
}

/* Inside a dropdown only the page you are actually on takes the bold weight and
   keeps its underline drawn; the ancestor rows above it stay regular, so the
   trail is visible without three rows competing to look current. */
.primary-navigation__menu .sub-menu .current-menu-item>a,
.primary-navigation__menu .sub-menu .current_page_item>a {
    font-weight: 700;
}

.primary-navigation__menu .sub-menu .current-menu-item>a::after,
.primary-navigation__menu .sub-menu .current_page_item>a::after {
    transform: scaleX(1);
    background: var(--color-bg-inverse);
}

@media (prefers-reduced-motion: reduce) {
    .primary-navigation__menu>.menu-item-has-children>a::after {
        transition: none;
    }
}

/* -------------------------------------------------------------------------- *
 * Mobile action tabs (tablet / mobile)
 * -------------------------------------------------------------------------- */

.header-tabs {
    display: flex;
    border-top: 1px solid rgba(43, 52, 58, 0.12);
}

.header-tab {
    display: flex;
    flex: 1 1 0;
    align-items: center;
    justify-content: center;
    gap: 10px;
    min-height: 60px;
    padding: 10px;
    background: none;
    border: 0;
    border-left: 1px solid rgba(43, 52, 58, 0.12);
    color: var(--color-bg-inverse);
    font-family: var(--font-body);
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-decoration: none;
    text-transform: uppercase;
    cursor: pointer;
}

.header-tab:first-child {
    border-left: 0;
}

.header-tab:hover,
.header-tab:focus-visible {
    color: var(--color-accent-dark);
}

.header-tab .icon {
    width: 22px;
    height: 22px;
    flex: 0 0 auto;
}

/* CSS hamburger — three bars that morph into an X when the drawer is open. */
.header-tab__burger,
.header-tab__burger::before,
.header-tab__burger::after {
    display: block;
    width: 22px;
    height: 2px;
    background: currentcolor;
    transition: transform 0.2s ease, opacity 0.2s ease;
}

.header-tab__burger {
    position: relative;
    flex: 0 0 auto;
}

.header-tab__burger::before,
.header-tab__burger::after {
    position: absolute;
    left: 0;
    content: "";
}

.header-tab__burger::before {
    top: -7px;
}

.header-tab__burger::after {
    top: 7px;
}

.header-tab--menu[aria-expanded="true"] .header-tab__burger {
    background: transparent;
}

.header-tab--menu[aria-expanded="true"] .header-tab__burger::before {
    transform: translateY(7px) rotate(45deg);
}

.header-tab--menu[aria-expanded="true"] .header-tab__burger::after {
    transform: translateY(-7px) rotate(-45deg);
}

/* -------------------------------------------------------------------------- *
 * Off-canvas drawers + backdrop
 * -------------------------------------------------------------------------- */

.drawer-backdrop {
    position: fixed;
    inset: 0;
    z-index: 900;
    background: rgba(0, 0, 0, 0.5);
}

.drawer {
    position: fixed;
    top: 0;
    bottom: 0;
    z-index: 1000;
    display: flex;
    flex-direction: column;
    width: min(340px, 85vw);
    background: var(--color-bg-inverse);
    color: var(--color-white);
    overflow-y: auto;
    /* Delay hiding until the slide-out finishes; show immediately on open. */
    visibility: hidden;
    transition: transform 0.3s ease, visibility 0s linear 0.3s;
}

.drawer--left {
    left: 0;
    transform: translateX(-100%);
}

.drawer--right {
    right: 0;
    transform: translateX(100%);
}

.drawer.is-open {
    transform: translateX(0);
    visibility: visible;
    transition: transform 0.3s ease, visibility 0s;
}

.drawer__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 16px 20px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}

.drawer__title {
    font-family: var(--font-heading);
    font-size: 16px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

.drawer__close {
    display: inline-flex;
    padding: 6px;
    background: none;
    border: 0;
    color: var(--color-white);
    cursor: pointer;
}

.drawer__close .icon {
    width: 22px;
    height: 22px;
}

.drawer__close:hover,
.drawer__close:focus-visible {
    color: var(--color-accent-light);
}

.drawer__body {
    padding: 8px 0 24px;
}

/* Drawer navigation. */
.drawer-navigation__menu,
.drawer-navigation__menu .sub-menu {
    margin: 0;
    padding: 0;
    list-style: none;
}

.drawer-navigation__menu a {
    display: block;
    padding: 14px 20px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    color: var(--color-white);
    font-family: var(--font-heading);
    font-size: 14px;
    letter-spacing: 0.08em;
    text-decoration: none;
    text-transform: uppercase;
}

.drawer-navigation__menu a:hover,
.drawer-navigation__menu a:focus-visible {
    color: var(--color-accent-light);
}

/* Active page in the drawer — a left teal bar marks the current item; its parent
   rows (ancestors of a nested active page) just take the accent colour. */
.drawer-navigation__menu .current-menu-item>a,
.drawer-navigation__menu .current_page_item>a {
    color: var(--color-accent-light);
    box-shadow: inset 3px 0 0 var(--color-accent-light);
}

.drawer-navigation__menu .current-menu-parent>a,
.drawer-navigation__menu .current-menu-ancestor>a,
.drawer-navigation__menu .current-page-parent>a,
.drawer-navigation__menu .current-page-ancestor>a,
.drawer-navigation__menu .current_page_parent>a,
.drawer-navigation__menu .current_page_ancestor>a {
    color: var(--color-accent-light);
}

.drawer-navigation__menu .sub-menu a {
    padding-left: 36px;
    font-size: 15px;
    text-transform: none;
}

/* Third level sits one step deeper than the second. */
.drawer-navigation__menu .sub-menu .sub-menu a {
    padding-left: 52px;
}

/*
 * Collapsible submenus. A parent row becomes [ link | + toggle ]; the submenu
 * (full-width, wraps to its own line) is hidden until the row gets .is-open.
 * The toggle button is injected by main.js, so no-JS users still see the links
 * (the collapse only applies when the .js class is present on <html>).
 */
.drawer-navigation__menu .menu-item-has-children {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
}

.drawer-navigation__menu .menu-item-has-children>a {
    flex: 1 1 auto;
}

.drawer-navigation__menu .submenu-toggle {
    position: relative;
    flex: 0 0 auto;
    width: 56px;
    padding: 0;
    background: none;
    border: 0;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    color: var(--color-white);
    cursor: pointer;
}

.drawer-navigation__menu .submenu-toggle::before,
.drawer-navigation__menu .submenu-toggle::after {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 14px;
    height: 2px;
    margin: -1px 0 0 -7px;
    background: currentcolor;
    transition: transform 0.2s ease;
    content: "";
}

/* Vertical bar rotates flat when open: + becomes -. */
.drawer-navigation__menu .submenu-toggle::after {
    transform: rotate(90deg);
}

.drawer-navigation__menu .submenu-toggle[aria-expanded="true"]::after {
    transform: rotate(0deg);
}

/* Submenu always wraps onto its own full-width row within the flex parent. */
.drawer-navigation__menu .menu-item-has-children>.sub-menu {
    flex: 0 0 100%;
}

/*
 * JS present: submenu collapses to zero height and animates open. main.js sets
 * an inline max-height (the measured scrollHeight) so the slide is accurate.
 * visibility flips off after the collapse finishes, so collapsed links drop out
 * of the tab order.
 */
.js .drawer-navigation__menu .sub-menu {
    overflow: hidden;
    max-height: 0;
    visibility: hidden;
    transition: max-height 0.3s ease, visibility 0s linear 0.3s;
}

.js .drawer-navigation__menu .menu-item-has-children.is-open>.sub-menu {
    visibility: visible;
    transition: max-height 0.3s ease, visibility 0s;
}

/* Contact drawer blocks. */
.contact-block {
    display: flex;
    gap: 14px;
    padding: 16px 20px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.contact-block__icon {
    width: 20px;
    height: 20px;
    flex: 0 0 auto;
    color: var(--color-accent-light);
}

.contact-block__label {
    display: block;
    margin-bottom: 4px;
    color: var(--color-accent-light);
    font-size: 12px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

.contact-block__body a {
    color: var(--color-white);
    text-decoration: none;
}

.contact-block__body a:hover,
.contact-block__body a:focus-visible {
    color: var(--color-accent-light);
}

.contact-hours {
    margin: 0;
    padding: 0;
    list-style: none;
    line-height: 1.7;
}

.contact-social {
    display: flex;
    gap: 18px;
    padding: 20px;
}

.contact-social__link {
    display: inline-flex;
    color: var(--color-white);
}

.contact-social__link .icon {
    width: 22px;
    height: 22px;
}

.contact-social__link:hover,
.contact-social__link:focus-visible {
    color: var(--color-accent-light);
}

/* Lock page scroll while a drawer is open. */
body.drawer-open {
    overflow: hidden;
}

/* -------------------------------------------------------------------------- *
 * Tab labels: hidden by default (narrow phones — icons carry the UI), revealed
 * from 600px up. Mobile-first, so the sr-only state is the base.
 * -------------------------------------------------------------------------- */

.header-tab__label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

@media (min-width: 600px) {
    .header-tab__label {
        position: static;
        width: auto;
        height: auto;
        margin: 0;
        overflow: visible;
        clip: auto;
    }
}

/* -------------------------------------------------------------------------- *
 * Desktop: top bar + nav row on, mobile tabs off.
 * -------------------------------------------------------------------------- */

@media (min-width: 1024px) {
    .site-topbar {
        display: block;
        background: var(--color-bg-inverse);
        border-bottom: 1px solid rgba(255, 255, 255, 0.12);
    }

    /*
     * Two rows: logo and CTA share the top one, the menu gets a full-width row
     * of its own underneath. Collapses to a single line at the wide breakpoint
     * below, once there is room for all three side by side.
     */
    .site-header__main {
        display: grid;
        align-items: center;
        justify-content: space-between;
        column-gap: 32px;
        grid-template-columns: 200px auto;
        grid-template-areas:
            "logo cta"
            "nav  nav";
        padding-bottom: 16px;
    }

    .site-branding {
        grid-area: logo;
        justify-content: flex-start;
    }

    .site-branding .custom-logo {
        max-height: 96px;
    }

    .site-nav {
        grid-area: nav;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .site-header__cta {
        grid-area: cta;
        display: flex;
        justify-content: flex-end;
    }

    .header-tabs {
        display: none;
    }
}

/* -------------------------------------------------------------------------- *
 * Wide desktop: logo, menu and CTA all fit on one line.
 * -------------------------------------------------------------------------- */

@media (min-width: 1400px) {
    .site-header__main {
        grid-template-columns: 200px 1fr auto;
        grid-template-areas: "logo nav cta";
        padding-bottom: 0;
    }
}

/* -------------------------------------------------------------------------- *
 * Reduced motion: no slide/morph animation.
 * -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {

    .site-header,
    .drawer,
    .header-tab__burger,
    .header-tab__burger::before,
    .header-tab__burger::after,
    .primary-navigation__menu .sub-menu a::after,
    .drawer-navigation__menu .sub-menu,
    .drawer-navigation__menu .submenu-toggle::before,
    .drawer-navigation__menu .submenu-toggle::after {
        transition: none;
    }
}

/*#endregion*/


/*#region Page hero*/
/*
 * Universal interior-page hero: every page that is not the homepage opens with
 * this band, so second-level pages all start the same way.
 *
 * Markup contract:
 *
 *   <section class="page-hero">
 *       <div class="page-hero__media" aria-hidden="true">[responsive_image …]</div>
 *       <div class="wrapper page-hero__inner">
 *           <p class="eyebrow">…</p>
 *           <h1>…</h1>
 *           <p>…</p>                          <!-- optional intro -->
 *           <div class="page-hero__actions">…</div>
 *       </div>
 *   </section>
 *
 * Copy left on a quiet tinted ground, photo right, bleeding to the screen edge.
 * Below 900px the two stack, photo first — which is what the DOM order already
 * says, so nothing needs reordering and the visual sequence never drifts from
 * the tab sequence.
 *
 * Only .page-hero__inner and the <h1> are required. Leave out .page-hero__media
 * and the band is a flat tinted panel with centred copy — the right answer for a
 * page with no photograph worth showing, and the reason nothing here assumes an
 * image. Do not add .section-padding to the <section>; this band owns its own
 * vertical rhythm, and the utility would pad the photo column too.
 *
 * The ground is --color-bg-muted-dark, not white, so the band reads as a header
 * rather than as the first content section — and being light, the copy is the
 * ordinary --color-text (15.65:1) instead of the reversed-out white this hero
 * used to carry. The eyebrow takes --color-accent-dark, 4.51:1 on this ground:
 * that is why it is the dark accent here and the light one on dark surfaces.
 *
 * Nothing sits on top of the photograph, so there is no scrim — the copy has
 * its own half of the band. If a page ever needs copy *over* an image, that is
 * .home-hero in assets/css/pages/home.css, scrim contrast sums included.
 *
 * The photo is a real <img> (media library, srcset) rather than a CSS
 * background, so it stays swappable from wp-admin and still gets responsive
 * sources. Its wrapper is aria-hidden: it is decoration, the message is the
 * text beside it.
 *
 * Buttons: this band is light, so .btn (graphite fill) and .btn.outline are the
 * variants that read here. .btn.secondary is a white fill and all but vanishes.
 */

.page-hero {
    position: relative;
    display: grid;
    grid-template-columns: 1fr;
    align-items: stretch;
    background: var(--color-bg-muted-dark);
    color: var(--color-text);
    overflow: hidden;
}

.page-hero__media {
    line-height: 0;
    aspect-ratio: 4 / 3;
}

.page-hero__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/*
 * Two columns of real content set the band's height between them, so the copy
 * carries its own padding — unlike a centred-in-min-height hero, nothing else
 * is holding it off the top and bottom edges.
 */
.page-hero__inner {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding-top: 40px;
    padding-bottom: 40px;
}

.page-hero__inner > *:last-child {
    margin-bottom: 0;
}

.page-hero__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1em;
    margin-top: 1.5em;
}

.page-hero .eyebrow {
    color: var(--color-accent-dark);
}

/* No photo: nothing to sit beside, so the copy centres in a band that still
   needs a floor under it. A browser without :has() keeps the left-aligned
   single column, which is a plain layout rather than a broken one. */
.page-hero:not(:has(.page-hero__media)) {
    min-height: 240px;
}

.page-hero:not(:has(.page-hero__media)) .page-hero__inner {
    text-align: center;
}

.page-hero:not(:has(.page-hero__media)) .page-hero__actions {
    justify-content: center;
}

@media (min-width: 900px) {
    .page-hero:has(.page-hero__media) {
        grid-template-columns: 1fr 1fr;
    }

    /*
     * DOM order is media then copy, so the copy is placed back into column 1
     * explicitly. Doing it here rather than with `order` keeps the mobile stack
     * (photo on top) coming straight from the markup.
     *
     * .page-hero__inner still carries .wrapper, whose max-width and auto margins
     * would centre the copy inside its own half — out of line with every other
     * section on the page. They are reset, and the left padding is rebuilt to
     * land exactly where .wrapper's content starts: half the leftover space
     * once the wrapper hits its max width, plus the wrapper's own gutter. Below
     * that width the first term clamps to 0 and the gutter alone is left, which
     * is what .wrapper does too. So the h1 sits on the same vertical line as
     * the body copy further down the page, at any viewport.
     */
    .page-hero:has(.page-hero__media) .page-hero__inner {
        grid-column: 1;
        grid-row: 1;
        max-width: none;
        margin: 0;
        padding-top: 64px;
        padding-bottom: 64px;
        padding-right: 56px;
        padding-left: calc(max(0px, (100vw - var(--wrapper-width)) / 2) + var(--wrapper-gutter));
    }

    .page-hero__media {
        grid-column: 2;
        grid-row: 1;
        aspect-ratio: auto;
    }
}

/*#endregion*/


/*#region Page CTA*/
/*
 * Closing call to action: heading, one sentence, then the booking button with a
 * click-to-call line beside it. Every conversion-relevant page ends this way
 * (CLAUDE.md §8) — the homepage included — so it lives here rather than being
 * re-typed in each page stylesheet.
 */

.page-cta {
    background: var(--color-bg-inverse);
    color: var(--color-text-inverse);
}

.page-cta__inner {
    text-align: center;
}

.page-cta__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 12px 24px;
    margin-top: 24px;
}

/* The "or call us" line is a <p> sitting next to the button in this row. */
.page-cta__actions>p {
    margin: 0;
}

/* --color-accent-light is 7.35:1 on the navy ground; the base accent is 3.98:1
   and would fail AA for link text here. */
.page-cta__call a {
    color: var(--color-accent-light);
    font-weight: 700;
}

/*#endregion*/


/*#region Split row*/
/*
 * A photo beside a block of copy — the layout the site reaches for constantly
 * (homepage trust rows, the "how it works" sequence on a service page, and on
 * from there), so it lives here once instead of being re-typed per page.
 *
 *   <div class="split">
 *       <div class="split__media">[responsive_image …]</div>
 *       <div class="split__body">…</div>
 *   </div>
 *
 * Write the markup the same way every time — media first, copy second — and add
 * .split--reverse to the rows whose photo should sit on the right. Below 900px
 * the row is a column and every variant stacks photo-then-copy.
 *
 * Reordering visually is safe here in a way it would not be generally: the two
 * halves are a picture and the prose about it, so either sequence reads the
 * same, and .split__media holds an image with nothing focusable inside it — so
 * the tab order cannot disagree with what is on screen.
 *
 * Modifiers:
 *   .split--reverse  photo on the right.
 *   .split--stretch  the photo fills the row's full height instead of keeping
 *                    its natural one. For a row whose copy is a long list: a
 *                    fixed-ratio photo would leave a gap under itself.
 *
 * Pages tune what is theirs on top of this — column widths, row spacing, a
 * background — without restating the layout.
 */

.split {
    display: flex;
    flex-direction: column;
    gap: 32px;
}

.split+.split {
    margin-top: 56px;
}

.split__media {
    display: flex;
    line-height: 0;
}

.split__media img {
    width: 100%;
    object-fit: cover;
}

/* The body is a run of prose; its outer margins are the row's job, not its. */
.split__body> :first-child {
    margin-top: 0;
}

.split__body> :last-child {
    margin-bottom: 0;
}

@media (min-width: 900px) {
    .split {
        flex-direction: row;
        align-items: center;
        gap: 56px;
    }

    .split--reverse {
        flex-direction: row-reverse;
    }

    /*
     * flex-basis 0 rather than auto is what makes the halves equal: sized from
     * the free space alone, so a long caption or a tall photo cannot widen its
     * own column. min-width lifts the automatic minimum that would otherwise
     * let a long unbroken string (a URL, a phone number) push past 50%.
     *
     * Both live inside the media query because on the mobile column the main
     * axis is vertical, where `flex: 1` would divide the HEIGHT between photo
     * and copy instead of the width.
     */
    .split>* {
        flex: 1 1 0;
        min-width: 0;
    }

    .split--stretch {
        align-items: stretch;
    }

    .split--stretch .split__media img {
        height: 100%;
    }
}

/*#endregion*/


/*#region Breadcrumbs*/
/*
 * inc/breadcrumbs.php renders an <ol> and only on nested pages, so this is the
 * first thing on an interior page, sitting on white above the hero band.
 *
 * The list marker is dropped and replaced by a "/" drawn between items: the
 * order is already carried by the <ol> and by aria-current on the last item, so
 * the separator is decoration and is hidden from assistive tech.
 *
 * The trail must survive a narrow screen without pushing the page sideways —
 * it wraps rather than scrolling, since a wrapped breadcrumb is still readable.
 */

.breadcrumbs {
    padding-top: 14px;
    padding-bottom: 14px;
    font-size: 16px;
    border-top: 1px solid var(--color-accent-light);
}

.breadcrumbs__list {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 8px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.breadcrumbs__item {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
}

.breadcrumbs__item+.breadcrumbs__item::before {
    content: "/";
    color: var(--color-accent-dark);
}

.breadcrumbs__link {
    color: var(--color-text);
    text-decoration: none;
}

.breadcrumbs__link:hover,
.breadcrumbs__link:focus-visible {
    color: var(--color-accent-dark);
    text-decoration: underline;
}

/* The page you are on: not a link, and said so with aria-current in the markup.
   Weight rather than colour alone, so it is not a colour-only distinction. */
.breadcrumbs__current {
    font-weight: 700;
}

/*#endregion*/


/*#region Term tip*/
/*
 * A "?" button next to a piece of jargon, opening a small panel that explains
 * it (assets/js/main.js drives the open/close). Hover is a convenience, not the
 * mechanism: the trigger is a real <button>, so the tip is reachable from the
 * keyboard and on touch, the pointer can travel into the panel without it
 * closing (WCAG 1.4.13), and Escape closes it and returns focus.
 *
 * The panel is built from phrasing elements (<span>s set to display: block)
 * because it lives inside a <p> — a <div> in there would be invalid HTML.
 */

.tip {
    position: relative;
    display: inline-block;
}

.tip__trigger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.4em;
    height: 1.4em;
    margin-left: 0.4em;
    padding: 0;
    border: 1px solid currentColor;
    border-radius: 50%;
    background: none;
    color: inherit;
    font: inherit;
    font-size: 0.7em;
    line-height: 1;
    cursor: pointer;
}

.tip__trigger:hover,
.tip__trigger[aria-expanded="true"] {
    border-color: var(--color-accent-dark);
    background: var(--color-accent-dark);
    color: var(--color-white);
}

/* The tip usually hangs off a label that is uppercase, letter-spaced and
   coloured; the panel is body copy and resets all of it. */
.tip__panel:not([hidden]) {
    display: block;
}

.tip__panel {
    position: absolute;
    top: calc(100% + 10px);
    left: 0;
    z-index: 5;
    width: min(420px, 78vw);
    max-height: 60vh;
    overflow-y: auto;
    padding: 18px 20px;
    border-top: 3px solid var(--color-accent);
    background: var(--color-white);
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
    color: var(--color-text);
    font-family: var(--font-body);
    font-size: 15px;
    font-weight: 500;
    line-height: 1.5;
    letter-spacing: normal;
    text-align: left;
    text-transform: none;
}

.tip__title {
    display: block;
    margin-bottom: 0.6em;
    font-family: var(--font-heading);
    font-size: 17px;
    font-weight: 700;
}

.tip__text {
    display: block;
}

.tip__text+.tip__text {
    margin-top: 0.8em;
}

/*#endregion*/


/* Layout utilities. */

.wrapper {
    width: 100%;
    max-width: var(--wrapper-width);
    margin: 0 auto;
    padding-right: var(--wrapper-gutter);
    padding-left: var(--wrapper-gutter);
}

.wrapper-text {
    max-width: var(--wrapper-text-width);
}

.full-w {
    width: 100%;
}

.section-padding {
    padding-top: 48px;
    padding-bottom: 48px;
}

.eyebrow {
    margin: 0 0 0.5em;
    font-size: 16px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
}

@media (min-width: 1024px) {
    .eyebrow {
        font-size: 20px;
    }
}

/*
 * Centred intro above a grid or card row: eyebrow, heading, one lead sentence.
 * Shared by every section that opens that way, so the measure and the spacing
 * below it stay identical across the site.
 *
 * The eyebrow accent is scoped to here rather than set on .eyebrow globally:
 * on a dark band the eyebrow inherits white, and --color-accent-dark would be
 * unreadable there.
 */
.section__head {
    max-width: 44em;
    margin: 0 auto 40px;
    text-align: center;
}

.section__head .eyebrow {
    color: var(--color-accent-dark);
}

.section__head p:last-child {
    margin-bottom: 0;
}

/* The "see everything" link that closes a section whose body is a grid or a
   slider — used after the service cards, the doctors and the reviews, so it is
   defined once rather than per section. */
.section__more {
    margin: 40px 0 0;
    text-align: center;
}

.pipe::after {
    content: "|";
    margin: 0 0.5em;
}

.pipe:last-child::after {
    content: none;
}

@media (min-width: 769px) {
    .section-padding {
        padding-top: 72px;
        padding-bottom: 72px;
    }
}

@media (min-width: 1025px) {
    .section-padding {
        padding-top: 96px;
        padding-bottom: 96px;
    }
}

/* Check list --------------------------------------------------------------- */

.check-list {
    margin: 1em 0 0;
    padding: 0;
    list-style: none;
}

.check-list li {
    position: relative;
    margin-bottom: 10px;
    padding-left: 30px;
}

.check-list li::before {
    content: "✓";
    position: absolute;
    top: 0;
    left: 0;
    font-weight: 700;
    color: var(--color-accent-dark);
}

.band--dark .check-list li::before {
    color: var(--color-accent-light);
}

.check-list--columns {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0 24px;
}

@media (min-width: 480px) {
    .check-list--columns {
        grid-template-columns: 1fr 1fr;
    }
}


/*#region Slider*/
/*
 * Generic horizontal slider, driven by main.js ([data-slider],
 * .slider__viewport, .slider__track, .slider__slide, [data-slider-prev|next]).
 * Shared component, not review-specific — the JS binds every [data-slider].
 *
 * The track is moved with a transform, not by scrolling: a scroll container
 * fights its own snap points, and Chrome throttles smooth scrolling to nothing
 * in a background tab. A transform is deterministic and cheap to composite.
 *
 * No-JS fallback: without the .js class on <html> the viewport is a plain
 * scrollable row, so every slide is still reachable. Once JS is present the
 * viewport clips instead and the buttons take over.
 *
 * Motion is a transform transition, so the global prefers-reduced-motion floor
 * further up this file already collapses it — no guard needed here.
 */

.slider__viewport {
    overflow-x: auto;
}

.js .slider__viewport {
    overflow: hidden;
}

.slider__track {
    display: flex;
    gap: 24px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.js .slider__track {
    transition: transform 0.45s ease;
}

.slider__slide {
    flex: 0 0 100%;
}

/* Two slides from tablet, three from laptop. The basis subtracts the gaps the
   row carries, so a whole number of slides fills the viewport exactly — which
   is also what lets main.js derive how many are on stage. */
@media (min-width: 700px) {
    .slider__slide {
        flex-basis: calc((100% - 24px) / 2);
    }
}

@media (min-width: 1024px) {
    .slider__slide {
        flex-basis: calc((100% - 48px) / 3);
    }
}

/* Controls ----------------------------------------------------------------- */

.slider__controls {
    display: none;
    gap: 12px;
    justify-content: center;
    margin-top: 24px;
}

.js .slider__controls {
    display: flex;
}

.slider__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    padding: 0;
    background: var(--color-bg);
    border: 1px solid var(--color-accent-dark);
    border-radius: 50%;
    color: var(--color-accent-dark);
    cursor: pointer;
    transition: background-color 0.2s ease, color 0.2s ease;
}

.slider__btn:hover:not(:disabled) {
    background: var(--color-accent-dark);
    color: var(--color-white);
}

.slider__btn:focus-visible {
    outline: 3px solid var(--color-accent-dark);
    outline-offset: 3px;
}

/* At the ends. Reduced opacity is the visual cue; the real state is the
   disabled attribute, which assistive tech reads directly, so this is not
   colour-only meaning. */
.slider__btn:disabled {
    opacity: 0.35;
    cursor: default;
}

.slider__btn .icon {
    width: 22px;
    height: 22px;
}

/* One chevron asset, turned to point each way. */
.slider__btn--prev .icon {
    transform: rotate(90deg);
}

.slider__btn--next .icon {
    transform: rotate(-90deg);
}

/*
 * Desktop: the arrows leave the row underneath and flank the slides instead,
 * so the eye does not have to travel down past the cards to reach them. Below
 * this width they stay centred under the slider, where a thumb can reach them.
 *
 * A three-column grid rather than absolute positioning: the buttons occupy
 * real space beside the viewport, so they cannot overlap a card, and the track
 * simply measures narrower — main.js reads the slide width at runtime, so
 * nothing there needs to know this layout exists.
 *
 * .slider__controls becomes display: contents so its two buttons become grid
 * items of .slider directly. It is a plain <div> with no semantics of its own,
 * so dissolving its box costs nothing; its margin-top is dropped with it.
 */
@media (min-width: 1024px) {
    .js .slider {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr) auto;
        align-items: center;
        column-gap: 20px;
    }

    .js .slider__viewport {
        grid-area: 1 / 2;
    }

    .js .slider__controls {
        display: contents;
    }

    .js .slider__btn--prev {
        grid-area: 1 / 1;
    }

    .js .slider__btn--next {
        grid-area: 1 / 3;
    }
}

/*#endregion*/


/*#region Service cards*/
/*
 * [service_cards] output (inc/shortcodes.php). Lives here rather than in
 * pages/home.css because the same shortcode is meant for the Services landing
 * page and any section page that lists its children.
 *
 * One photo per card with the service name centred on top. The photo carries a
 * graphite tint at rest; hovering the card — or focusing its link — takes that
 * tint to fully opaque, so the card becomes a solid graphite tile.
 *
 * Contrast: the title is white on the tinted photo. Even over a pure white
 * photo the 0.62 tint composites to ~#7c8185 — 3.94:1, which clears the 3:1
 * floor for large text (the title is 24px bold, well past the 18.66px bold
 * threshold). Do not lower the tint or shrink the title without redoing that
 * sum; on hover the tint is solid and the ratio is 12.69:1.
 */

.service-cards {
    display: grid;
    grid-template-columns: 1fr;
    gap: 20px;
    margin: 0;
    padding: 0;
    list-style: none;
}

/* Photo and title share one grid cell, so the title centres over the image
   without absolute positioning or a hardcoded height. */
.service-card {
    position: relative;
    display: grid;
    overflow: hidden;
    border-radius: 3px;
    background: var(--color-bg-inverse);
    color: var(--color-text-inverse);
}

.service-card__media,
.service-card__title {
    grid-area: 1 / 1;
}

.service-card__media {
    position: relative;
    aspect-ratio: 4 / 3;
    line-height: 0;
}

.service-card__image {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* No Featured Image: a plain teal tile instead of a photo. It still darkens to
   the same navy on hover, so a card without a picture behaves like the others.
   White title over the tinted teal is 9.22:1. */
.service-card__media--empty {
    background: var(--color-accent-dark);
}

.service-card__media::after {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--color-bg-inverse);
    opacity: 0.62;
    transition: opacity 0.3s ease;
}

/* The tint above is a positioned element, which would paint over ordinary
   sibling content — the title has to be positioned to stay on top of it. */
.service-card__title {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0;
    padding: 20px;
    font-size: 24px;
    line-height: 1.2;
    text-align: center;
}

.service-card__link {
    color: var(--color-text-inverse);
    text-decoration: none;
}

/* Stretched link: the whole card is clickable while the link's accessible name
   stays just the service title. */
.service-card__link::after {
    content: "";
    position: absolute;
    inset: 0;
}

/* The global focus ring is --color-accent-dark, which is too dark to see on
   this navy ground; the light variant is 7.35:1 against it. */
.service-card__link:focus-visible {
    outline-color: var(--color-accent-light);
}

.service-card:hover .service-card__media::after,
.service-card:focus-within .service-card__media::after {
    opacity: 1;
}

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

@media (min-width: 1024px) {
    .service-cards {
        grid-template-columns: repeat(4, 1fr);
        gap: 24px;
    }
}

/*#endregion*/


/*#region Footer*/
/*
 * Site footer.
 *
 * Layout: brand + contact, appointments CTA, quick links, then a legal bar.
 * Dark navy ground, white text, teal accents — the real Mid County Dental
 * brand colors (see design/), not the theme's gold placeholder.
 */

/*
 * "Our Location" block — practice details beside an embedded map, sitting
 * directly above the footer. Mobile-first: details stack over the map, the two
 * sit side by side from 900px up.
 */

.site-location {
    background: var(--color-bg-muted);
}

/* Only one h2 and two h3s live in this section, so the shared look rides on the
   elements and the classes below carry only what differs between them. */
.site-location h2 {
    margin: 0 0 0.8em;
    text-align: center;
    color: var(--color-bg-inverse);
}

.site-location h3 {
    color: var(--color-bg-inverse);
}

.site-location__grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 32px;
}

@media (min-width: 900px) {
    .site-location__grid {
        grid-template-columns: 1fr 1fr;
        gap: 48px;
        align-items: center;
    }
}

.site-location__name {
    margin: 0 0 0.7em;
}

.site-location__subtitle {
    margin: 1.2em 0 0.5em;
    font-size: 22px;
}

.site-location__contacts,
.site-location__hours {
    margin: 0;
    padding: 0;
    list-style: none;
    font-weight: 600;
}

.site-location__contacts li {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 12px;
}

.site-location__contacts .icon {
    width: 20px;
    height: 20px;
    flex: 0 0 auto;
    color: var(--color-accent);
}

.site-location__contacts a {
    color: var(--color-accent-dark);
    text-decoration: none;
}

.site-location__contacts a:hover,
.site-location__contacts a:focus-visible {
    text-decoration: underline;
    text-underline-offset: 2px;
}

.site-location__hours li {
    margin-bottom: 6px;
}

/* Reserve the map's space before the iframe loads, so nothing shifts. */
.site-location__map {
    height: 100%;
    min-height: 300px;
}

.site-location__frame {
    display: block;
    width: 100%;
    height: 100%;
    border: 0;
}

.site-footer {
    background: var(--color-bg-inverse);
    color: var(--color-white);
    font-size: 18px;
}

/* Width and side gutters come from .wrapper on the same element. */
.site-footer__inner {
    display: grid;
    grid-template-columns: 1fr;
    gap: 40px;
    padding-top: 56px;
    padding-bottom: 56px;
}

@media (min-width: 768px) {
    .site-footer__inner {
        grid-template-columns: 1.4fr 1fr 0.8fr;
        gap: 56px;
    }

    .site-location__map {
        min-height: 400px;
    }
}

/* Columns ------------------------------------------------------------------ */

.site-footer__col> :first-child {
    margin-top: 0;
}

.site-footer__heading {
    margin: 0 0 0.75em;
    font-size: 24px;
    color: var(--color-white);
}

/* Brand + contact ---------------------------------------------------------- */

.site-footer__logo {
    margin-bottom: 24px;
}

/*
 * The logo is a full-colour raster whose graphite half ("DENTAL SPECIALTIES"
 * and the implant screw) is nearly the same value as --color-bg-inverse, so it
 * disappears against the footer. brightness(0) crushes every pixel to black,
 * invert(1) lifts it to white. Filters touch RGB but not alpha, so the screw's
 * semi-transparent gradient stays semi-transparent and reads as soft grey
 * depth inside the solid white outline — intended, not a miss. Drop this
 * filter if a white logo variant is ever uploaded, or it will invert to dark.
 */
.site-footer__logo img {
    height: auto;
    max-width: 220px;
    filter: brightness(0) invert(1);
}

.site-footer__contact {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 12px;
    font-size: 1em;
    text-decoration: none;
}

.site-footer__contact .icon {
    flex: 0 0 auto;
    font-size: 1em;
    color: var(--color-accent-light);
}

.site-footer__contact:hover {
    color: var(--color-accent-light);
}

.site-footer__social {
    display: flex;
    gap: 18px;
    margin-top: 20px;
}

.site-footer__social-link {
    display: inline-flex;
    color: var(--color-white);
}

.site-footer__social-link .icon {
    font-size: 1.25em;
}

.site-footer__social-link:hover {
    color: var(--color-accent-light);
}

/* Appointments ------------------------------------------------------------- */

.site-footer__appointments p {
    margin: 0 0 1.25em;
    font-size: 1em;
}

.site-footer__cta {
    display: inline-block;
}

/* Quick links -------------------------------------------------------------- */

.site-footer__menu {
    margin: 0;
    padding: 0;
    list-style: none;
    font-weight: 600;
}

.site-footer__menu li {
    margin-bottom: 10px;
}

.site-footer__menu a {
    font-size: 1em;
    text-decoration: none;
}

.site-footer__menu a:hover {
    color: var(--color-accent-light);
}

/* Legal bar ---------------------------------------------------------------- */

.site-footer__bar {
    border-top: 1px solid rgba(255, 255, 255, 0.12);
}

/* Width and side gutters come from .wrapper on the same element. */
.site-footer__bar-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding-top: 20px;
    padding-bottom: 20px;
    text-align: center;
}

.site-footer__copyright {
    margin: 0;
    color: var(--color-accent-light);
}

.site-footer__legal-menu {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px 16px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.site-footer__legal-menu a {
    text-decoration: none;
}

.site-footer__legal-menu a:hover {
    color: var(--color-accent-light);
}

/*#endregion*/