/*
 * Grand River Periodontics — shared inner-page system.
 *
 * Loaded on the hand-built page-{slug}.php templates (Office, Services, LANAP,
 * New Patients, Doctor Referrals, Contact). It is the sibling of home.css: the
 * homepage scopes its rules under .grp-home, these scope under .grp-page, and
 * both draw on the same site-wide tokens and .grp-btn buttons from style.css.
 *
 * The visual language is the homepage's: a sequence of solid brand-colour
 * grounds (.grp-section--*), Solora for display, Neue Swiss for text. Buttons,
 * the palette and the fixed-header spacing all come from style.css, so this file
 * only adds what inner pages need: a page-opening band, prose layout, and a few
 * content components (service index, facts list, ordered steps, info blocks).
 */

.grp-page {
    /* Local type + rhythm scale, mirroring home.css so the two read as one site.
       The titlebar is the homepage hero's own scale — same ceiling, same
       composition — so every inner page opens exactly the way the homepage
       does, not a step below it. */
    --step-title: clamp(1.9rem, 6.8vw, 4.9rem);
    --step-h2:    clamp(1.7rem, 3.6vw, 2.6rem);
    --step-h3:    clamp(1.15rem, 1.9vw, 1.4rem);
    --step-lead:  clamp(1.05rem, 1.5vw, 1.3rem);
    --step-body:  clamp(1rem, 1.05vw, 1.0625rem);

    --gap-section: clamp(3.5rem, 8vw, 7rem);
    --gap-block:   clamp(1.5rem, 3vw, 2.5rem);
    --gutter:      clamp(1.5rem, 5vw, 5rem);
    /* 84rem: matches .grp-footer__inner and .grp-affil__inner exactly, so every
       inner-page section lines up edge-to-edge with the "Office hours &
       location" band every page ends on, instead of running narrower. */
    --wrap:        84rem;   /* section content cap */
    --measure:     68ch;    /* prose line-length cap, per the 65–75ch rule */

    color: var(--text-body);
    background-color: var(--bg-page);
}

/* Full-bleed: drop Avada's #content width cap the same way the homepage does. */
body:not(.page-template-template-home) #main > .fusion-row,
.grp-page.full-width {
    max-width: none;
    width: 100%;
    margin: 0;
    padding: 0;
}

/* ---------- Shared section grounds ---------------------------------------- */
/* Same grounds as the homepage, defined here because home.css is homepage-only.
   The two 25% tints composite over the page's paper for near-white fields that
   only ever raise contrast. */
.grp-page .grp-section {
    position: relative;
    padding: var(--gap-section) var(--gutter);
    isolation: isolate;
}

.grp-page .grp-section.grp-doctor{
    position: relative;
    /* Final word on padding — the widths below used to live on this same
       element and won the padding-top/bottom cascade too; kept as one
       declaration now that they've moved off. Even top/bottom, same as the
       --square variant just below: this section isn't meant to read flush
       against whatever follows it. */
    padding: 80px 0;
    isolation: isolate;
}

.grp-page .grp-section--offwhite { background-color: rgb(var(--c-paper)); color: var(--text-body); }
.grp-page .grp-section--lightblue { background-color: rgba(var(--c-sky), 0.25); color: rgb(var(--c-ink)); }
.grp-page .grp-section--taupe { background-color: rgba(var(--c-taupe), 0.25); color: rgb(var(--c-ink)); }
.grp-page .grp-section--slate { background-color: var(--brand-primary); color: var(--text-on-dark); }
.grp-page .grp-section--navy { background-color: var(--brand-dark); color: var(--text-on-dark); }

.grp-page .grp-wrap { max-width: var(--wrap); margin-inline: auto; }

/* ---------- Typography ---------------------------------------------------- */
.grp-page h2,
.grp-page h3 { color: var(--text-heading); }

.grp-page .grp-section--slate :is(h2, h3),
.grp-page .grp-section--navy :is(h2, h3) { color: var(--text-on-dark); }

.grp-page .grp-h2 {
    font-family: var(--font-display, 'Solora', Georgia, serif);
    font-weight: 400;
    font-size: var(--step-h2);
    line-height: 1.08;
    /* Solora's own kerning table crowds a handful of pairs (P+a is the worst
       offender, e.g. "Payment & financial arrangements") badly enough for ink
       to touch at display sizes. Negative tracking made that worse; positive
       tracking is the fix, not editing around the pairs that trigger it. */
    letter-spacing: 0.02em;
    text-wrap: balance;
    margin: 0 0 20px 0;
}

.grp-page .grp-h3 {
    font-size: var(--step-h3);
    font-weight: 600;
    line-height: 1.25;
    letter-spacing: -0.01em;
    text-wrap: balance;
    margin: 0 0 0.5em;
}

.grp-page .grp-lead {
    font-size: var(--step-lead);
    line-height: 1.5;
    max-width: var(--measure);
    text-wrap: pretty;
    margin: 0 0 20px;
}

.grp-page .grp-section--slate .grp-lead,
.grp-page .grp-section--slate p,
.grp-page .grp-section--navy .grp-lead { color: rgb(var(--c-white)); }

/* Prose: readable measure, generous rhythm. */
.grp-page .grp-prose { max-width: 100%;}
.grp-page .grp-prose > * + * { margin-top: 1.1em; }
.grp-page .grp-prose p,
.grp-page .grp-prose li {
    font-size: var(--step-body);
    line-height: 1.65;
    text-wrap: pretty;
}
.grp-page .grp-section--offwhite :is(p, li),
.grp-page .grp-section--lightblue :is(p, li),
.grp-page .grp-section--taupe :is(p, li) { color: rgba(var(--c-ink), 0.86); }
.grp-page .grp-section--slate :is(p, li),
.grp-page .grp-section--navy :is(p, li) { color: rgb(var(--c-white)); }

/* In-text links, one consistent look site-wide: blue on light grounds, white
   on dark grounds — every content link (prose, address, list, form hint)
   reads the same regardless of which section it lands in. */
.grp-page .grp-section :is(p, li, address, dd) a:not(.grp-btn) {
    color: var(--brand-primary);
    text-underline-offset: 0.15em;
    text-decoration-thickness: 1px;
    transition: color 0.2s ease;
    font-weight: 700;
}
.grp-page .grp-section--slate :is(p, li, address, dd) a:not(.grp-btn),
.grp-page .grp-section--navy :is(p, li, address, dd) a:not(.grp-btn) { color: rgb(var(--c-sky)); }
.grp-page .grp-section :is(p, li, address, dd) a:not(.grp-btn):hover { color: var(--brand-dark); }
.grp-page .grp-section--slate :is(p, li, address, dd) a:not(.grp-btn):hover,
.grp-page .grp-section--navy :is(p, li, address, dd) a:not(.grp-btn):hover { color: rgb(var(--c-white)); }
.grp-page .grp-section :is(p, li, address, dd) a:not(.grp-btn):focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 2px;
    border-radius: 2px;
}

/* Credential line under a name (as on the homepage doctor block). */
.grp-page .grp-credential {
    color: var(--brand-primary);
    font-weight: 600;
    letter-spacing: 0.01em;
    margin: -0.4em 0 var(--gap-block);
}
.grp-page .grp-section--slate .grp-credential,
.grp-page .grp-section--navy .grp-credential { color: rgb(var(--c-sky)); }

/* ---------- Image titlebar ----------------------------------------------- */
/* The homepage hero's still-image sibling, built to the same composition: a
   dark scrim over a full-bleed image, type anchored to the bottom rather
   than centred, carrying the page H1 so every inner page opens the way the
   homepage does — at half its height, so the titlebar reads as an opening
   band rather than a second full-viewport hero. Scrim stops and motion are
   reused verbatim from .grp-hero; only the height differs. */
.grp-pagehero {
    position: relative;
    display: grid;
    place-items: end center;
    min-height: 70svh;
    padding: calc(var(--gutter) * 2) var(--gutter) clamp(4rem, 11vh, 7.5rem);
    overflow: hidden;
    isolation: isolate;
    text-align: center;
    background-color: rgb(var(--c-ink));
    color: var(--text-on-dark);
    padding-bottom: 60px;
}

/* Shorter opening band on /videos/ — a plain title band with no photo/video
   behind it, so it doesn't need the same height as the rest of the site's
   inner-page heroes. */
body.grp-videos .grp-pagehero {
    min-height: 30svh;
}

.grp-pagehero__media {
    position: absolute;
    inset: 0;
    z-index: 0;
}

/*.grp-pagehero__image {*/
/*    width: 100%;*/
/*    height: 100%;*/
/*    object-fit: cover;*/
/*    object-position: center;*/
/*    display: block;*/
/*}*/

.grp-pagehero__image {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 50% 20%;
    display: block;
}


/* Same stops as .grp-hero::after: strongest at the bottom where the type
   sits, a lighter wash at the top so the white nav keeps its contrast. */
.grp-pagehero::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    background: linear-gradient(to bottom,
        rgba(var(--c-ink), 0.52) 0%,
        rgba(var(--c-ink), 0.16) 26%,
        rgba(var(--c-ink), 0.30) 58%,
        rgba(var(--c-ink), 0.74) 100%);
}

/* Fallback when a page passes no image: the plain solid-ink band. */
.grp-pagehero--plain::after { display: none; }

.grp-pagehero__inner {
    position: relative;
    z-index: 2;
    width: 100%;
    max-width: 62rem;
    margin-inline: auto;
}
.grp-pagehero__eyebrow {
    display: inline-block;
    font-family: var(--font-body);
    font-size: clamp(0.8rem, 1.05vw, 0.95rem);
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: rgb(var(--c-white));
    margin: 0 0 clamp(0.5rem, 1.2vw, 1rem);
}
.grp-pagehero__title {
    font-family: var(--font-display, 'Solora', Georgia, serif);
    font-weight: 400;
    font-size: var(--step-title);
    line-height: 0.98;
    /* 0.006em let Solora's own kerning touch ink on tight pairs (P+a, e.g.
       "New Patients") at this size — widened to clear it. */
    letter-spacing: 0.02em;
    text-wrap: balance;
    margin: 0;
    color: var(--text-on-dark);
    /* Same treatment as .grp-hero__display: Solora is high-contrast, a soft
       shadow keeps hairlines legible over a photograph. */
    text-shadow: 0 1px 28px rgba(var(--c-ink), 0.45);
}
.grp-pagehero__lead {
    font-size: var(--step-lead);
    line-height: 1.5;
    color: rgb(var(--c-white));
    max-width: 52ch;
    text-wrap: pretty;
    margin: clamp(1.25rem, 2.6vw, 2rem) auto 0;
}
.grp-pagehero__actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.85rem;
    margin: clamp(1.4rem, 3.4vw, 1.75rem) 0 0;
}

/* Same breakpoints as .grp-hero, at half its pixel floors to match: a tall
   band still reads as drama on a desktop banner, but as wasted scroll
   distance on a short phone screen. */
@media (max-width: 1024px) {
    .grp-pagehero { min-height: 480px; padding-bottom: 30px; }
}
@media (max-width: 640px) {
    .grp-pagehero { min-height: 300px; padding-bottom: 30px; }
    .grp-pagehero__actions { flex-direction: column; align-items: stretch;  }
}

/* ---------- Doctor portrait (identical to the homepage's own section) ----- */
/* Same classes, same rules as .grp-doctor in home.css — ported verbatim so the
   office page's opening bio renders pixel-identical to the homepage's Dr.
   Sinacola section, portrait column stretched to match whatever height the
   bio copy actually runs to (the same "stretch + height:100% down the chain"
   fix .grp-lanap__image uses on the homepage). Colour comes for free from the
   shared ground + typography rules above, since this section carries the
   same .grp-section--offwhite class the homepage one does. */
/* Grid + width cap live on this inner wrapper, not on .grp-doctor itself —
   .grp-doctor is the <section> that also paints the ground colour, and a
   max-width there would cap the background box along with the content,
   leaving colour bands on either side instead of a full-bleed ground. */
.grp-doctor__inner {
    display: grid;
    grid-template-columns: minmax(0, 6fr) minmax(0, 6fr);
    align-items: stretch;
    gap: clamp(2rem, 6vw, 6rem);
    max-width: var(--wrap);
    margin-inline: auto;
}

.grp-doctor__portrait {
    margin: 0;
    /* A stretched grid item's height is auto by default, which measures the
       image at its own aspect ratio and undoes the stretch. Forcing 100%
       here is what carries the row's height down to the <img>. */
    height: 100%;
}

.grp-doctor__portrait img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    max-width: 560px;
}

/* .grp-video-trigger's own rules only set width:100% — matching the image's
   height:100%/max-width here too so the button's box lines up with the
   visible photo exactly, not just its width. */
.grp-doctor__portrait .grp-video-trigger {
    height: 100%;
    max-width: 560px;
}

.grp-doctor__body {
    align-self: center;
    padding-bottom: 0;
}

.grp-doctor__body > p:last-child {
    margin-bottom: 0;
}

/* ---------- Square portrait variant (Doctor Referrals' "Meet Dr. Sinacola") */
/* Opts out of the stretch-to-row-height treatment above: a fixed 1:1 crop,
   centred in the row instead of matching whatever height the bio copy runs
   to. Scoped to .grp-doctor--square so /about/'s own portrait, which still
   wants the taller stretched crop, is unaffected. */
.grp-doctor--square .grp-doctor__inner {
    align-items: center;
}

.grp-doctor--square .grp-doctor__portrait {
    height: auto;
    align-self: center;
}

.grp-doctor--square .grp-doctor__portrait img {
    height: auto;
    aspect-ratio: 1 / 1;
    object-fit: cover;
}

.grp-doctor--square .grp-doctor__portrait .grp-video-trigger {
    height: auto;
    max-width: 560px;
}

/* Even top/bottom padding for this instance only — the shared .grp-doctor
   rule is top-heavy (80px 0 0) so the stretched portrait above reads as
   flush with whatever section follows it. */
.grp-page .grp-section.grp-doctor--square {
    padding-bottom: 80px;
}

@media (max-width: 1024px) {
    .grp-doctor__inner {
        grid-template-columns: 1fr;
        gap: clamp(2rem, 5vw, 4rem);
        max-width: var(--wrap);
    }

    .grp-page .grp-section.grp-doctor {
        padding-bottom: var(--gap-section);
    }

    .grp-page .grp-section.grp-doctor--square {
        padding-bottom: 80px;
    }

    /* Single column means she's no longer sharing a row to stretch against —
       back to a fixed ratio rather than a 100%-height figure with nothing
       definite to be 100% of. */
    .grp-doctor__portrait {
        height: auto;
    }

    .grp-doctor__portrait img {
        height: auto;
        aspect-ratio: 1000 / 1200;
    }

    .grp-doctor--square .grp-doctor__portrait img {
        aspect-ratio: 1 / 1;
    }

    .grp-doctor__body {
        align-self: auto;
        padding-bottom: 0;
        max-width: 44rem;
    }
}

/* ---------- Video testimonials (identical to the homepage's own section) - */
/* Same classes, same rules as .grp-testimonials/.grp-testimonial in
   home.css — ported verbatim so /testimonials/ renders pixel-identical to
   the homepage's "Hear from our patients" section. The play ring is a
   deliberately different icon language from the arrow rows elsewhere on
   this page — "play a video" is a different action from "go to a page". */
.grp-testimonials__inner {
    max-width: 84rem;
    margin-inline: auto;
}

.grp-testimonials__grid {
    list-style: none;
    margin: clamp(2.5rem, 5vw, 3.5rem) 0 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: clamp(1.5rem, 3vw, 2.5rem);
}

.grp-testimonial {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 1 / 1;
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: 4px;
    overflow: hidden;
    background: none;
    cursor: pointer;
    isolation: isolate;
}

.grp-testimonial img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.5s var(--ease);
}

/* Scrim: just enough to keep the ring legible over a bright photo, without
   flattening the thumbnail into a dark rectangle. */
.grp-testimonial::after {
    content: "";
    position: absolute;
    inset: 0;
    background: rgba(var(--c-ink), 0.22);
    transition: background-color 0.35s var(--ease);
}

.grp-testimonial:hover img,
.grp-testimonial:focus-visible img {
    transform: scale(1.05);
}

.grp-testimonial:hover::after,
.grp-testimonial:focus-visible::after {
    background: rgba(var(--c-ink), 0.34);
}

.grp-testimonial:focus-visible {
    outline: 2px solid rgb(var(--c-sky));
    outline-offset: 4px;
}

.grp-testimonial__play {
    position: absolute;
    inset: 0;
    z-index: 1;
    display: grid;
    place-items: center;
}

.grp-testimonial__ring {
    width: clamp(3.25rem, 6vw, 4rem);
    height: clamp(3.25rem, 6vw, 4rem);
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: rgba(var(--c-ink), 0.4);
    border: 2px solid rgba(var(--c-paper), 0.85);
    transition: transform 0.35s var(--ease), background-color 0.35s var(--ease);
}

.grp-testimonial:hover .grp-testimonial__ring,
.grp-testimonial:focus-visible .grp-testimonial__ring {
    transform: scale(1.08);
    background: var(--brand-primary);
}

.grp-testimonial__ring svg {
    width: 1.1rem;
    height: 1.1rem;
    /* Optical centring: a triangle's own visual weight sits left of its
       bounding box centre, so it's nudged right to read as centred. */
    margin-left: 2px;
    fill: rgb(var(--c-paper));
}

.grp-testimonial__caption {
    margin: 20px 0 0;
    font-size: 1.2rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-align: center;
    color: rgb(var(--c-white));
}

/* ---------- Two-column media + body -------------------------------------- */
.grp-media {
    display: grid;
    grid-template-columns: 1fr;
    gap: clamp(2rem, 5vw, 4rem);
    align-items: center;
    max-width: var(--wrap);
    margin-inline: auto;
}
@media (min-width: 60rem) {
    .grp-media { grid-template-columns: 1fr 1fr; }
    .grp-media--flip .grp-media__figure { order: 2; }

    /* Opt-in modifier: stretches the figure to match the body column's own
       height rather than the image's natural ratio — same "stretch +
       height:100% down the chain" fix as .grp-doctor__portrait and
       .grp-lanap__image. A stretched grid item's height is auto by default,
       which measures the image at its own ratio and undoes the stretch, so
       height:100% has to be restated at every level to actually reach the
       <img>. Only above 60rem, where .grp-media is actually two columns
       sharing a row to stretch against — in the stacked single-column
       layout below that there's nothing to match, so this intentionally
       falls back to the default natural-ratio rule above. */
    .grp-media--stretch { align-items: stretch; }
    .grp-media--stretch .grp-media__figure { height: 100%; }
    .grp-media--stretch .grp-media__figure img { height: 100%; object-fit: cover; }
    /* The body column now stretches to match the image's height too (that's
       what makes align-items:stretch work at the grid level), but a plain
       block's content still just sits at the top of that taller box by
       default — this re-centers the body's own content within it, so short
       copy reads centered against the image rather than pinned to its top. */
    .grp-media--stretch .grp-media__body {
        display: flex;
        flex-direction: column;
        justify-content: center;
    }

    /* Opt-in modifier: the figure follows the page down the section instead
       of scrolling away as soon as its own (short) content clears the
       viewport — used on Doctor Referrals, where the form beside it runs
       much taller than the image. align-items:start (rather than the base
       rule's center) gives the figure's grid cell the column's full height
       to stick within; --grp-header-h is the same measured fixed-header
       offset used for scroll-padding-top elsewhere, so the pinned image
       clears the header instead of sitting under it. Only above 60rem,
       where the two columns actually sit side by side — sticky has nothing
       to mean in the stacked single-column layout below that. */
    .grp-media--sticky-figure { align-items: start; }
    .grp-media--sticky-figure .grp-media__figure {
        position: sticky;
        top: calc(var(--grp-header-h, 90px) + 1.5rem);
    }
}
/* Capped height + crop, at every width — the source image runs much wider
   than tall, and left at its own ratio would run far past 400px on a narrow
   single-column stack too. */
.grp-media--sticky-figure .grp-media__figure {
    max-height: 400px;
}
.grp-media--sticky-figure .grp-media__figure img {
    height: 400px;
    object-fit: cover;
}
.grp-media__figure { margin: 0; }
.grp-media__figure img {
    width: 100%;
    height: auto;
    display: block;
    border-radius: 4px;
}

/* A plain figure's height is otherwise whatever its own image's native ratio
   works out to at the column's width — some of the source photos are close
   to square, which at a ~40rem column rendered upwards of 40rem tall next to
   two or three lines of copy. Capping it (and cropping the overflow off the
   top/bottom, not the sides, since these are landscape-ish photos to begin
   with) keeps every plain figure in a consistent, moderate range regardless
   of the source photo's own ratio. Excludes --square (that ratio is
   intentional) and --stretch (which already sizes the figure off the body
   column on purpose, for the opposite problem — image shorter than the
   copy). Only above 60rem, matching every other .grp-media rule that reasons
   about the two-column layout. */
@media (min-width: 60rem) {
    .grp-media:not(.grp-media--stretch) .grp-media__figure:not(.grp-media__figure--square) img {
        max-height: 26rem;
        object-fit: cover;
    }
}



/* ---------- Video-popup trigger (button wrapping a .grp-media image) ----- */
/* Same play-ring-over-a-photo pattern as the homepage's .grp-testimonial
   buttons, generalised to wrap any single .grp-media image rather than a
   fixed testimonial grid. pages.js swaps a YouTube iframe into the shared
   #grp-video-modal using the button's data-yt-id. */
.grp-video-trigger {
    position: relative;
    display: block;
    width: 100%;
    padding: 0;
    margin: 0;
    border: 0;
    background: none;
    cursor: pointer;
}
.grp-video-trigger__play {
    position: absolute;
    inset: 0;
    z-index: 1;
    display: grid;
    place-items: center;
}
.grp-video-trigger__ring {
    width: clamp(3.25rem, 6vw, 4rem);
    height: clamp(3.25rem, 6vw, 4rem);
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: rgba(var(--c-ink), 0.4);
    border: 2px solid rgba(var(--c-paper), 0.85);
    transition: transform 0.35s ease, background-color 0.35s ease;
}
.grp-video-trigger:hover .grp-video-trigger__ring,
.grp-video-trigger:focus-visible .grp-video-trigger__ring {
    transform: scale(1.08);
    background: var(--brand-primary);
}
.grp-video-trigger__ring svg {
    width: 1.1rem;
    height: 1.1rem;
    /* Optical centring: a triangle's own visual weight sits left of its
       bounding box centre, so it's nudged right to read as centred. */
    margin-left: 2px;
    fill: rgb(var(--c-paper));
}
.grp-video-trigger:focus-visible {
    outline: 2px solid rgb(var(--c-sky));
    outline-offset: 4px;
}

/* ---------- Video modal (shared by any .grp-video-trigger on the page) --- */
.grp-video-modal {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: grid;
    place-items: center;
    padding: clamp(1.25rem, 4vw, 3rem);
}
.grp-video-modal[hidden] { display: none; }
.grp-video-modal__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(var(--c-ink), 0.88);
}
.grp-video-modal__dialog {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 1280px;
}
.grp-video-modal__frame {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    background: rgb(var(--c-ink));
    border-radius: 4px;
    overflow: hidden;
}
.grp-video-modal__frame iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
}
.grp-video-modal__close {
    position: absolute;
    top: 0.75rem;
    right: 0.75rem;
    z-index: 2;
    width: 2.25rem;
    height: 2.25rem;
    display: grid;
    place-items: center;
    background: rgba(var(--c-ink), 0.55);
    border: 1px solid rgba(var(--c-paper), 0.5);
    border-radius: 50%;
    color: rgb(var(--c-paper));
    cursor: pointer;
    transition: background-color 0.3s ease, border-color 0.3s ease;
}
.grp-video-modal__close:hover,
.grp-video-modal__close:focus-visible {
    background: rgba(var(--c-ink), 0.8);
    border-color: rgb(var(--c-paper));
}
.grp-video-modal__close svg {
    width: 0.85rem;
    height: 0.85rem;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: square;
}
.grp-video-modal__close:focus-visible {
    outline: 2px solid rgb(var(--c-sky));
    outline-offset: 3px;
}
/* Body scroll lock while the modal is open — toggled by pages.js. */
html.grp-modal-open,
html.grp-modal-open body { overflow: hidden; }

/* ---------- Video library (/videos/) -------------------------------------- */
/* Gallery grid: a card per video. The thumbnail itself is the play trigger
   (pops the shared modal, like .grp-video-trigger elsewhere); the title and
   "Watch video" link below are a separate, real navigation link to that
   video's own dedicated page — same idea as pmaxdentalmarketing.com's own
   client-testimonials page, just with an inline preview on top of it. Two
   independent controls, so they can't nest inside one another. */
.grp-video-grid {
    list-style: none;
    margin: var(--gap-block) 0 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: clamp(1.75rem, 3vw, 2.5rem);
}

@media (max-width: 900px) {
    .grp-video-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 600px) {
    .grp-video-grid { grid-template-columns: 1fr; }
}

.grp-video-card__thumb {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 1 / 1;
    padding: 0;
    border: 0;
    border-radius: 4px;
    overflow: hidden;
    background: rgb(var(--c-ink));
    cursor: pointer;
    isolation: isolate;
}

.grp-video-card__thumb img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.5s var(--ease);
}

.grp-video-card__thumb::after {
    content: "";
    position: absolute;
    inset: 0;
    background: rgba(var(--c-ink), 0.18);
    transition: background-color 0.35s var(--ease);
}

.grp-video-card__thumb:hover img,
.grp-video-card__thumb:focus-visible img {
    transform: scale(1.05);
}

.grp-video-card__thumb:hover::after,
.grp-video-card__thumb:focus-visible::after {
    background: rgba(var(--c-ink), 0.3);
}

.grp-video-card__thumb:hover .grp-video-trigger__ring,
.grp-video-card__thumb:focus-visible .grp-video-trigger__ring {
    transform: scale(1.08);
    background: var(--brand-primary);
}

.grp-video-card__thumb:focus-visible {
    outline: 2px solid var(--brand-primary);
    outline-offset: 4px;
}

.grp-video-card__body {
    display: block;
    margin-top: 1rem;
}

.grp-video-card__title {
    display: block;
    font-family: var(--font-display, 'Solora', Georgia, serif);
    font-weight: 700;
    font-size: clamp(1.05rem, 1.6vw, 1.25rem);
    line-height: 1.3;
    color: var(--brand-dark);
    text-wrap: balance;
    margin: 30px 0;
    text-align: center;
    min-height: 52px;
}

.grp-video-card__watch {
    width: 100%;
    min-width: 0;
}

/* Watch page: a large lazy-loaded facade (poster + play button) that swaps
   to a real iframe on click — same idea as .grp-video-trigger, just inline
   on the page instead of opening the shared modal. */
.grp-watch {
    max-width: 860px;
}

.grp-watch-video {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 16 / 9;
    border-radius: 4px;
    overflow: hidden;
    background: rgb(var(--c-ink));
    isolation: isolate;
}

.grp-watch-video img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.grp-watch-video::after {
    content: "";
    position: absolute;
    inset: 0;
    background: rgba(var(--c-ink), 0.22);
    pointer-events: none;
}

.grp-watch-video__play {
    position: absolute;
    inset: 0;
    z-index: 1;
    display: grid;
    place-items: center;
    width: 100%;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
}

.grp-watch-video__play .grp-video-trigger__ring {
    width: clamp(4rem, 8vw, 5.5rem);
    height: clamp(4rem, 8vw, 5.5rem);
}

.grp-watch-video__play:hover .grp-video-trigger__ring,
.grp-watch-video__play:focus-visible .grp-video-trigger__ring {
    transform: scale(1.08);
    background: var(--brand-primary);
}

.grp-watch-video__play:focus-visible {
    outline: 2px solid rgb(var(--c-sky));
    outline-offset: 4px;
}

.grp-watch-video iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
}

/* Opt-in modifier: most .grp-media images run at their own natural ratio,
   which varies section to section — this forces a guaranteed 1:1 crop for
   the ones that call for it (e.g. "How the laser works" on the LANAP page),
   without touching every other .grp-media figure on the site. */
.grp-media__figure--square img {
    aspect-ratio: 1 / 1;
    object-fit: cover;
}

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

/* ---------- Labeled two-column split (ported from the homepage's own
   .grp-referral__split) --------------------------------------------------- */
/* A short highlight pair — uppercase label, hairline rule, one short
   paragraph — rather than another paragraph tacked onto the one before it. */
.grp-split {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: clamp(1.75rem, 4vw, 3rem);
    margin: var(--gap-block) 0 0;
}
.grp-split__col > :last-child { margin-bottom: 0; }
.grp-split__label {
    display: block;
    font-family: var(--font-body);
    font-size: 0.9rem;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: rgba(var(--c-ink), 0.78);
    margin: 0 0 0.75rem;
    padding-bottom: 0.75rem;
    border-bottom: 1px solid rgba(var(--c-ink), 0.4);
}
.grp-section--slate .grp-split__label,
.grp-section--navy .grp-split__label {
    color: rgba(var(--c-paper), 0.85);
    border-bottom-color: rgba(var(--c-paper), 0.4);
}

/* ---------- Full-width feature banner (ported from the homepage's own
   .grp-referral__banner) --------------------------------------------------- */
.grp-banner {
    margin: 0 0 var(--gap-block);
    max-width: var(--wrap);
    margin-inline: auto;
}
.grp-banner img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 8 / 3;
    object-fit: cover;
    border-radius: 4px;
    max-height: 420px;
}

/* Small caption naming a real team member under their photo. */
.grp-team-caption {
    margin: 0.85rem 0 0;
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    color: rgba(var(--c-ink), 0.65);
    text-align: center;
}

/* ---------- Signature CTA panel (wave mark + a phone number as its own
   display line) ------------------------------------------------------------ */
.grp-cta-panel {
    max-width: 34rem;
    margin-inline: auto;
    text-align: center;
}
/* Opt-in modifier: a couple of CTAs run two full sentences instead of one
   short line — at the default 34rem those wrap into three-plus narrow lines,
   so this gives them more room. (The child <p>'s own 760px max-width below
   is reachable only once the panel itself is wide enough to let it matter —
   at the default 34rem it was dead weight, silently clipped by this parent.) */
.grp-cta-panel--wide { max-width: 46rem; }
.grp-cta-panel p {
    max-width: 770px;
    margin-left: auto;
    margin-right: auto;
}
.grp-cta-panel .grp-cta-row { justify-content: center; }
.grp-cta-wave {
    display: block;
    width: clamp(6rem, 11vw, 9rem);
    height: auto;
    margin: 0 auto clamp(1.25rem, 2.4vw, 1.75rem);
}
.grp-cta-phone {
    display: inline-block;
    font-family: var(--font-display, 'Solora', Georgia, serif);
    font-size: clamp(1.75rem, 3.4vw, 2.5rem);
    font-weight: 400;
    letter-spacing: 0.01em;
    color: var(--brand-dark);
    text-decoration: none;
    margin: clamp(0.75rem, 2vw, 1.25rem) 0 0;
}
.grp-cta-phone:hover,
.grp-cta-phone:focus-visible { color: var(--brand-primary); text-decoration: underline; }

/* ---------- Service index (mechanics ported verbatim from the homepage's
   own .grp-care__index) ----------------------------------------------------- */
/* One link/row per service — an index, not a card grid. Same sliding
   underline + indent on hover, same corner arrow, as "What a periodontist
   treats" on the homepage. */
.grp-index {
    list-style: none;
    margin: var(--gap-block) 0 0;
    padding: 0;
    max-width: var(--wrap);
    margin-inline: auto;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(21rem, 1fr));
    gap: 0 clamp(2rem, 5vw, 4.5rem);
    border-top: 1px solid rgba(var(--c-taupe), 0.26);
}
.grp-index > li {
    margin: 0;
    border-bottom: 1px solid rgba(var(--c-taupe), 0.26);
}
.grp-index a {
    position: relative;
    display: block;
    padding: clamp(1.1rem, 2vw, 1.5rem) 1.75rem clamp(1.1rem, 2vw, 1.5rem) 0;
    text-decoration: none;
    color: inherit;
    transition: padding-inline-start 0.45s cubic-bezier(0.22, 1, 0.36, 1), color 0.3s ease;
}
.grp-index__name {
    display: block;
    margin: 0;
    font-family: var(--font-display, 'Solora', Georgia, serif);
    font-weight: 900;
    font-size: clamp(1.15rem, 1.8vw, 1.5rem);
    line-height: 1.2;
    letter-spacing: 0.015em;
    color: var(--brand-dark);
}
.grp-index__desc {
    display: block;
    margin: 0.5em 0 0;
    max-width: 34ch;
    font-size: var(--step-body);
    line-height: 1.6;
    color: rgba(var(--c-ink), 0.82);
    font-weight: 400;
}
/* The sliding rule: hidden at rest, grows in on hover. */
.grp-index a::before {
    content: "";
    position: absolute;
    left: 0;
    top: calc(clamp(1.1rem, 2vw, 1.5rem) + 0.6em);
    width: 0;
    height: 2px;
    background-color: var(--brand-primary);
    transition: width 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}
html body.services .grp-index a::before {
    display: none;
}
.grp-index a:hover,
.grp-index a:focus-visible {
    /* No padding-inline-start indent here on purpose — animating it shrinks
       the available text width, which can push a row onto an extra line and
       grow the box on hover. The underline and arrow below carry the
       hover state instead. */
    outline: none;
}
.grp-index a:hover::before,
.grp-index a:focus-visible::before {
    width: 1.7rem;
}
.grp-index a:focus-visible { box-shadow: inset 3px 0 0 var(--brand-primary); }

/* The "content links" rule above (.grp-page .grp-section :is(p,li,...) a)
   also matches this <a> — it's inside an <li> — and outscores this file's
   own .grp-index a at (0,3,2) vs (0,1,1), so its `transition: color 0.2s
   ease` silently replaced the whole transition list here, killing the
   padding-inline-start slide (it snapped instead of easing in). Restating
   the full list at equal-or-higher specificity is what makes hover move as
   one motion again — same fix, same cascade bug, as .grp-care__index on the
   homepage (see home.css). */
.grp-page .grp-section .grp-index a:not(.grp-btn) {
    transition: padding-inline-start 0.45s cubic-bezier(0.22, 1, 0.36, 1), color 0.3s ease;
}
.grp-index__arrow {
    position: absolute;
    right: 0;
    bottom: clamp(1.1rem, 2vw, 1.5rem);
    width: 1rem;
    height: 1rem;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: square;
    stroke-linejoin: miter;
    color: rgba(var(--c-navy), 1);
    pointer-events: none;
    transition: color 0.45s cubic-bezier(0.22, 1, 0.36, 1), transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}
.grp-index a:hover .grp-index__arrow,
.grp-index a:focus-visible .grp-index__arrow {
    color: var(--brand-primary);
    transform: translate(3px, -3px);
}

@media (max-width: 640px) {
    .grp-index a:hover::before,
    .grp-index a:focus-visible::before { width: 0; }
}

/* Two lines' worth of floor under the row name, so the description beneath
   starts at the same height across a row — same fix, same rationale, as
   .grp-care__name on the homepage. line-height is 1.2, so two lines is
   2.4em. Only above 800px, which is where this grid (identical
   repeat(auto-fit, minmax(21rem, 1fr))) switches from one column to two —
   in a single column there's nothing to align against and the floor would
   just open a gap under the short names. */
@media (min-width: 800px) {
    .grp-index__name {
        min-height: 2.4em;
    }
}

/* ---------- Editorial list (.grp-index's typography, without the link) --- */
/* For rows that have no page of their own to link to — a two-column index of
   name + description, same display-face name and hairline rows as
   .grp-index, just without the arrow or hover state a real link earns. */
.grp-list {
    list-style: none;
    margin: var(--gap-block) 0 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
    gap: 0 clamp(2rem, 5vw, 4rem);
    border-top: 1px solid rgba(var(--c-slate), 0.22);
    max-width: var(--wrap);
    margin-inline: auto;
}
.grp-list > li {
    margin: 0;
    padding: clamp(1.1rem, 2.2vw, 1.6rem) 0;
    border-bottom: 1px solid rgba(var(--c-slate), 0.22);
}
.grp-section--slate .grp-list > li,
.grp-section--navy .grp-list > li,
.grp-section--slate .grp-list,
.grp-section--navy .grp-list { border-color: rgba(var(--c-paper), 0.24); }
.grp-list__name {
    display: block;
    font-family: var(--font-display, 'Solora', Georgia, serif);
    font-weight: 400;
    font-size: clamp(1.2rem, 2.1vw, 1.6rem);
    line-height: 1.15;
    letter-spacing: -0.01em;
    color: var(--text-heading);
    margin: 0 0 0.4rem;
}
.grp-section--slate .grp-list__name,
.grp-section--navy .grp-list__name { color: var(--text-on-dark); }
.grp-list__desc {
    margin: 0;
    max-width: 60ch;
}

/* ---------- Facts / checklist -------------------------------------------- */
.grp-facts {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 0.85rem;
    max-width: var(--measure);
}
.grp-facts li {
    position: relative;
    padding-left: 2rem;
    font-size: 18px;
    line-height: 1.5;
}
.grp-facts li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.15em;
    width: 1.2rem;
    height: 1.2rem;
    border-radius: 50%;
    background: var(--brand-primary);
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M3.5 8.5l3 3 6-6.5'/%3E%3C/svg%3E") center / 0.85rem no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M3.5 8.5l3 3 6-6.5'/%3E%3C/svg%3E") center / 0.85rem no-repeat;
}
.grp-section--slate .grp-facts li::before,
.grp-section--navy .grp-facts li::before { background: rgb(var(--c-sky)); }

/* ---------- Ordered steps (only where order carries meaning) -------------- */
.grp-steps {
    list-style: none;
    counter-reset: step;
    margin: var(--gap-block) 0 0;
    padding: 0;
    display: grid;
    gap: clamp(1.25rem, 2.5vw, 2rem);
    /* Grid only stretches items to match the tallest item in their own row —
       fine when everything fits one row, but four uneven-length steps
       wrapping to a 2x2 grid otherwise left row 1 a different height than
       row 2. This matches every row's height to the tallest item across the
       whole grid instead, so every step reads as the same size regardless of
       how many end up sharing a row at a given width. */
    grid-auto-rows: 1fr;
}
@media (min-width: 48rem) {
    .grp-steps { grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }
}
.grp-steps > li { counter-increment: step; }
.grp-steps__n {
    font-family: var(--font-display, 'Solora', Georgia, serif);
    font-size: clamp(2rem, 4vw, 2.75rem);
    line-height: 1;
    color: var(--brand-primary);
    display: block;
    margin-bottom: 0.5rem;
}
.grp-steps__n::before { content: counter(step, decimal); }
.grp-section--slate .grp-steps__n,
.grp-section--navy .grp-steps__n { color: rgb(var(--c-sky)); }
.grp-steps h3 { margin-bottom: 0.35em; }

/* Opt-in modifier: the number sits inline with the heading text instead of
   stacked above it as its own oversized display line — used where a
   compact, inline-numbered heading reads better (e.g. "What to expect" on
   the LANAP page). Markup moves .grp-steps__n inside the <h3> as its first
   child rather than a sibling before it, since that's what actually lets it
   flow inline with the heading text instead of needing layout tricks to
   fake it. Scoped to this modifier so the default stacked style (e.g. "Your
   first visit" on the New Patients page) is untouched. */
.grp-steps--inline .grp-steps__n {
    display: inline;
    font-size: 1.3em;
    line-height: inherit;
    margin: 0;
}
.grp-steps--inline .grp-steps__n::before {
    content: counter(step, decimal) ". ";
}

/* ---------- Info block: address / hours / phone -------------------------- */
.grp-info {
    display: grid;
    gap: clamp(2rem, 5vw, 3.5rem);
    max-width: var(--wrap);
    margin-inline: auto;
}
@media (min-width: 52rem) { .grp-info { grid-template-columns: repeat(2, 1fr); } }
.grp-info__label {
    font-size: 0.9rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--brand-primary);
    margin: 0 0 0.75rem;
}
.grp-section--slate .grp-info__label,
.grp-section--navy .grp-info__label { color: rgb(var(--c-sky)); }
.grp-address { font-style: normal; font-size: var(--step-lead); line-height: 1.55; }
.grp-hours { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 0.4rem 1.5rem; max-width: 22rem; }
.grp-hours dt { font-weight: 600; }
.grp-hours dd { margin: 0; text-align: right; }
.grp-hours .is-closed { opacity: 0.6; }

/* Embedded Google map — sits under the address/hours pair on the Contact
   page. aspect-ratio keeps it a fixed, sane shape at any column width rather
   than the iframe's own intrinsic size, which browsers otherwise default to. */
.grp-mapembed {
    margin-top: var(--gap-block);
    border-radius: 4px;
    overflow: hidden;
    aspect-ratio: 4 / 2;
}
.grp-mapembed iframe {
    width: 100%;
    height: 100%;
    display: block;
    border: 0;
}

.grp-mapcard { display: block; margin-top: var(--gap-block); border-radius: 4px; overflow: hidden; }
.grp-mapcard img { width: 100%; height: auto; display: block; }

/* ---------- Generic two-column pairing (no image, unlike .grp-media) ------ */
/* For pairing two independent content blocks of different lengths (e.g. the
   Contact page's address/hours next to its form) — top-aligned rather than
   .grp-media's vertically-centred pairing, since centring would look odd
   when one side is much taller than the other. */
.grp-cols {
    display: grid;
    grid-template-columns: 1fr;
    gap: clamp(2.5rem, 6vw, 5rem);
    max-width: var(--wrap);
    margin-inline: auto;
    align-items: start;
}
@media (min-width: 60rem) {
    .grp-cols { grid-template-columns: 1fr 1fr; }
}

/* Form slot: the Gravity Form is dropped in by shortcode; this frames it. */
.grp-formwrap { max-width: 42rem; margin-inline: auto; }
/* Opt-in modifier: matches .grp-form--wide's own max-width — without this the
   wrapper's 42rem was clipping the wide referral form back down below its
   own cap, squeezing the split rows and checkbox grid it was sized for. */
.grp-formwrap--wide { max-width: 46rem; }

/* ---------- Hand-built contact form (no plugin dependency) ---------------- */
/* Honeypot: visually hidden, not display:none — a screen reader skips it via
   aria-hidden, but it stays in the DOM and tab order that only a script
   would ever find and fill in, which is what makes it work as a spam trap. */
.grp-form__hp {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}
.grp-form {
    max-width: 34rem;
    margin: var(--gap-block) 0 0;
}
/* Opt-in modifier: longer forms (e.g. the referral form's field count) need
   more breathing room than the contact form's single column. */
.grp-form--wide { max-width: 46rem; }
.grp-form__row {
    margin: 0 0 1.25rem;
    display: grid;
    gap: 0.4rem;
}
@media (min-width: 40rem) {
    /* Opt-in modifier: pairs two fields side by side (e.g. DOB + phone) on a
       wide form without affecting single-column rows elsewhere. Each pair
       is wrapped in its own .grp-form__field, so this only needs to lay
       out two grid items — the field wrapper is what actually keeps each
       label stacked with its own input (and, now, its own error message)
       rather than needing a column-auto-flow trick to pair flat siblings. */
    .grp-form__row--split {
        grid-template-columns: 1fr 1fr;
        column-gap: 1.5rem;
    }
}
.grp-form__field {
    display: grid;
    gap: 0.4rem;
    align-content: start;
}
.grp-form__row label {
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
.grp-section--slate .grp-form__row label,
.grp-section--navy .grp-form__row label { color: rgba(var(--c-paper), 0.85); }

/* Required-field marker. aria-hidden since the input's own `required`
   attribute already tells assistive tech that; this is the sighted-user
   signal, same --color-error token used for form validation elsewhere. */
.grp-required {
    color: var(--color-error);
    margin-left: 0.2em;
    font-weight: 700;
}
.grp-form__row :is(input:not([type="checkbox"]):not([type="radio"]), textarea, select) {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    width: 100%;
    font-family: var(--font-body);
    font-size: 1rem;
    font-weight: 500;
    padding: 0.5rem 0.5rem;
    border: 1.5px solid rgba(var(--c-ink), 0.7);
    border-radius: 2px;
    /*background-color: rgb(var(--c-paper));*/
    background-color: #fff;
    color: rgb(var(--c-ink));
    transition: border-color 0.25s ease, box-shadow 0.25s ease;
}
.grp-form__row textarea { resize: vertical; min-height: 8rem; }
.grp-form__row :is(input, textarea)::placeholder { color: rgba(var(--c-ink), 0.45); }
.grp-form__row :is(input:not([type="checkbox"]):not([type="radio"]), textarea, select):focus-visible {
    outline: none;
    border-color: var(--brand-primary);
    box-shadow: 0 0 0 3px rgba(var(--c-sky), 0.4);
}
/* Invalid state — set/cleared by pages.js as it runs the same fields
   through the browser's own constraint validation (required, type=email,
   etc., already on the markup). Higher specificity than the plain border
   rule above (an extra attribute selector), so it wins without !important. */
.grp-form__row :is(input:not([type="checkbox"]):not([type="radio"]), textarea, select)[aria-invalid="true"] {
    border-color: var(--color-error);
}
.grp-field-error {
    margin: 0.35rem 0 0;
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: normal;
    text-transform: none;
    color: var(--color-error) !important;
    background: #fff;
    padding: 4px;
    text-align: center;
    border-radius: 6px;
}
/* select loses its native dropdown arrow with appearance:none above, so a
   matching one is drawn here instead — same thin-stroke chevron as
   .grp-faq__icon, coloured to #121720 (--c-ink) since a background-image
   can't reference a CSS custom property. */

.grp-form__row select {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M2 5l6 6 6-6' fill='none' stroke='%23121720' stroke-width='1.6' stroke-linecap='square' stroke-linejoin='miter'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.6rem center;
    background-size: 0.9rem;
    padding-right: 2rem;
    cursor: pointer;
}
.grp-form__row input[type="file"] {
    padding: 0.6rem 1rem;
    font-size: 0.9rem;
    cursor: pointer;
}
.grp-form__row input[type="date"] {
    cursor: pointer;
}
.grp-form__hint {
    font-size: 0.85rem;
    font-weight: 400;
    letter-spacing: normal;
    text-transform: none;
    color: rgba(var(--c-ink), 0.65);
    margin: -0.2rem 0 0;
}
.grp-section--slate .grp-form__hint,
.grp-section--navy .grp-form__hint { color: rgba(var(--c-paper), 0.65); }

/* Checkbox group: a fieldset-style label followed by a wrapped grid of
   individual checkbox + text pairs (the referral form's treatment list). */
.grp-form__checks {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
    gap: 0.6rem 1.5rem;
    margin-top: 0.2rem;
}
.grp-form__check {
    display: flex;
    align-items: flex-start;
    gap: 0.55rem;
    font-size: 0.95rem;
    font-weight: 400;
    letter-spacing: normal;
    text-transform: none;
    cursor: pointer;
}
.grp-form__check input {
    width: 1.1rem;
    height: 1.1rem;
    margin-top: 0.15rem;
    flex-shrink: 0;
    accent-color: var(--brand-primary);
    cursor: pointer;
}
.grp-form__submit { margin-top: 2rem; }

.grp-form__notice {
    max-width: 34rem;
    margin: 0 0 var(--gap-block);
    padding: 0.85rem 1.1rem;
    border-radius: 2px;
    font-weight: 600;
}
.grp-form__notice--sent {
    background-color: rgba(var(--c-sky), 0.35);
    color: rgb(var(--c-ink));
}
.grp-form__notice--error {
    background-color: rgba(var(--c-taupe), 0.55);
    color: rgb(var(--c-ink));
}

/* CTA row shared across pages. */
.grp-cta-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin: var(--gap-block) 0 0;
}

/* ---------- Motion: reveal on scroll, enhancing a visible default --------- */
/* Same stagger as the homepage hero's grp-rise: eyebrow, then title, then
   lead, then the buttons last. */
.grp-pagehero__eyebrow,
.grp-pagehero__title,
.grp-pagehero__lead,
.grp-pagehero__actions { animation: grp-page-rise 1s cubic-bezier(0.22, 1, 0.36, 1) backwards; }
.grp-pagehero__eyebrow { animation-delay: 0.15s; }
.grp-pagehero__title { animation-delay: 0.28s; }
.grp-pagehero__lead { animation-delay: 0.36s; }
.grp-pagehero__actions { animation-delay: 0.46s; }

@keyframes grp-page-rise {
    from { opacity: 0; transform: translateY(1.25rem); }
    to { opacity: 1; transform: none; }
}

/* Sections start at 0.9 opacity (never hidden) and settle to full when seen.
   pages.js adds .grp-reveal-pending on load; if JS never runs, or reduced-motion
   is set, the content simply renders full. */
.grp-reveal-pending {
    opacity: 0.9;
    transform: translateY(1rem);
    transition: opacity 0.7s cubic-bezier(0.16, 1, 0.3, 1), transform 0.7s cubic-bezier(0.16, 1, 0.3, 1);
    will-change: opacity, transform;
}
.grp-reveal-pending.is-visible { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
    .grp-pagehero__eyebrow,
    .grp-pagehero__title,
    .grp-pagehero__lead,
    .grp-pagehero__actions { animation: none; }
    .grp-reveal-pending,
    .grp-reveal-pending.is-visible { opacity: 1; transform: none; transition: none; }
}

/* ---------- FAQ accordion -------------------------------------------------- */
/* Native <details>/<summary> — no JS, works with keyboard and screen readers
   out of the box. Hairline rows echo .grp-index's; the question uses the
   same display face as .grp-h3 rather than body weight, so it reads as a
   heading even collapsed. */
.grp-faq-title.grp-h2 {
    text-align: center;
}
.grp-faq {
    margin: 0 auto;
    max-width: 880px;
    border-top: 1px solid rgba(var(--c-taupe), 0.26);
}
.grp-faq__item {
    border-bottom: 1px solid rgba(var(--c-taupe), 0.26);
}
.grp-faq__q {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: clamp(1rem, 2vw, 1.4rem) 0;
    font-family: var(--font-display, 'Solora', Georgia, serif);
    font-weight: 700;
    font-size: clamp(1.05rem, 1.6vw, 1.25rem);
    line-height: 1.3;
    color: var(--brand-dark);
    cursor: pointer;
    list-style: none;
}
.grp-faq__q::-webkit-details-marker { display: none; }
.grp-faq__q:focus-visible {
    outline: 2px solid var(--brand-primary);
    outline-offset: 4px;
    border-radius: 2px;
}
.grp-faq__icon {
    flex-shrink: 0;
    width: 1rem;
    height: 1rem;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: square;
    stroke-linejoin: miter;
    color: rgba(var(--c-navy), 1);
    transition: transform 0.3s ease, color 0.3s ease;
}
.grp-faq__item[open] .grp-faq__icon {
    transform: rotate(180deg);
    color: var(--brand-primary);
}
.grp-faq__a {
    margin: 0 0 clamp(1rem, 2vw, 1.4rem);
}
.grp-faq__a p {
    font-size: var(--step-body);
    line-height: 1.65;
    color: rgba(var(--c-ink), 0.86);
    margin: 0;
}

/* ==========================================================================
   Gravity Forms, wearing the site's own form design
   --------------------------------------------------------------------------
   The hand-built markup above was replaced by gravity_form() embeds, which
   orphaned every .grp-form* rule in this file — GF emits .gfield / .gfield_label
   / .gform_footer instead. What was left dressing the forms was an unrelated
   .gform_wrapper block in style.css, written for the previous build's dark
   footer form: it hardcodes transparent fields with white labels. That reads
   acceptably on the slate contact panel and is unreadable on the light-blue
   referral panel, where white text sits on a light ground.

   So this maps GF's class names onto the SAME declarations .grp-form* uses,
   including the one thing the style.css block never had: labels and hints are
   dark by default and only go light inside .grp-section--slate / --navy, which
   is what makes one rule set work on both panels.

   Specificity: scoped `.grp-formwrap .gform_wrapper.gravity-theme` = (0,3,0),
   so descendants land at (0,4,x). That clears GF's own
   `.gform_wrapper.gravity-theme select` (0,2,1) and style.css's
   `html body .gform_wrapper select.gfield_select` (0,2,3) without !important
   and without depending on load order — which matters here because WP Rocket's
   used-CSS rewriting does not preserve the original stylesheet order.
   ========================================================================== */

/* ---- field rows ---------------------------------------------------------- */
.grp-formwrap .gform_wrapper.gravity-theme .gform_fields {
    grid-row-gap: 1.25rem;
}
.grp-formwrap .gform_wrapper.gravity-theme .gfield {
    display: grid;
    gap: 0.4rem;
    align-content: start;
}

/* ---- labels: dark on light grounds, light on slate/navy ------------------ */
.grp-formwrap .gform_wrapper.gravity-theme .gfield_label,
.grp-formwrap .gform_wrapper.gravity-theme legend.gfield_label {
    font-family: var(--font-body);
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: rgb(var(--c-ink));
    margin-bottom: 0;
    padding: 0;
}
.grp-section--slate .grp-formwrap .gform_wrapper.gravity-theme .gfield_label,
.grp-section--slate .grp-formwrap .gform_wrapper.gravity-theme legend.gfield_label,
.grp-section--navy .grp-formwrap .gform_wrapper.gravity-theme .gfield_label,
.grp-section--navy .grp-formwrap .gform_wrapper.gravity-theme legend.gfield_label {
    color: rgba(var(--c-paper), 0.85);
}

/* Required marker — same --color-error token the rest of the form uses. */
.grp-formwrap .gform_wrapper.gravity-theme .gfield_required {
    color: var(--color-error);
    font-weight: 700;
    font-style: normal;
    margin-left: 0.2em;
}

/* ---- text inputs, textarea, select --------------------------------------- */
.grp-formwrap .gform_wrapper.gravity-theme .gfield input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="file"]),
.grp-formwrap .gform_wrapper.gravity-theme .gfield textarea,
.grp-formwrap .gform_wrapper.gravity-theme .gfield select {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    width: 100%;
    box-sizing: border-box;
    min-height: 0;
    height: auto;
    font-family: var(--font-body);
    font-size: 1rem;
    font-weight: 500;
    line-height: 1.4;
    padding: 0.5rem;
    margin: 0;
    border: 1.5px solid rgba(var(--c-ink), 0.7);
    border-radius: 2px;
    background-color: #fff;
    background-image: none;
    color: rgb(var(--c-ink));
    transition: border-color 0.25s ease, box-shadow 0.25s ease;
}
.grp-formwrap .gform_wrapper.gravity-theme .gfield textarea {
    resize: vertical;
    min-height: 8rem;
}
.grp-formwrap .gform_wrapper.gravity-theme .gfield input::placeholder,
.grp-formwrap .gform_wrapper.gravity-theme .gfield textarea::placeholder {
    color: rgba(var(--c-ink), 0.45);
}
.grp-formwrap .gform_wrapper.gravity-theme .gfield input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="file"]):focus-visible,
.grp-formwrap .gform_wrapper.gravity-theme .gfield textarea:focus-visible,
.grp-formwrap .gform_wrapper.gravity-theme .gfield select:focus-visible {
    outline: none;
    border-color: var(--brand-primary);
    box-shadow: 0 0 0 3px rgba(var(--c-sky), 0.4);
}

/* select keeps its own chevron, since appearance:none removes the native one.
   Same thin-stroke mark and #121720 stroke as the hand-built form used. */
.grp-formwrap .gform_wrapper.gravity-theme .gfield select {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M2 5l6 6 6-6' fill='none' stroke='%23121720' stroke-width='1.6' stroke-linecap='square' stroke-linejoin='miter'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.6rem center;
    background-size: 0.9rem;
    padding-right: 2rem;
    cursor: pointer;
}
.grp-formwrap .gform_wrapper.gravity-theme .gfield input[type="date"] {
    cursor: pointer;
}
.grp-formwrap .gform_wrapper.gravity-theme .gfield input[type="file"] {
    width: 100%;
    box-sizing: border-box;
    padding: 0.6rem 1rem;
    font-family: var(--font-body);
    font-size: 0.9rem;
    border: 1.5px solid rgba(var(--c-ink), 0.7);
    border-radius: 2px;
    background-color: #fff;
    color: rgb(var(--c-ink));
    cursor: pointer;
}

/* ---- helper text --------------------------------------------------------- */
.grp-formwrap .gform_wrapper.gravity-theme .gfield_description,
.grp-formwrap .gform_wrapper.gravity-theme .gform_fileupload_rules {
    font-size: 0.85rem;
    font-weight: 400;
    letter-spacing: normal;
    text-transform: none;
    color: rgba(var(--c-ink), 0.65);
    padding-top: 0;
}
.grp-section--slate .grp-formwrap .gform_wrapper.gravity-theme .gfield_description,
.grp-section--slate .grp-formwrap .gform_wrapper.gravity-theme .gform_fileupload_rules,
.grp-section--navy .grp-formwrap .gform_wrapper.gravity-theme .gfield_description,
.grp-section--navy .grp-formwrap .gform_wrapper.gravity-theme .gform_fileupload_rules {
    color: rgba(var(--c-paper), 0.65);
}

/* ---- checkbox + radio groups -------------------------------------------- */
.grp-formwrap .gform_wrapper.gravity-theme .gfield_checkbox,
.grp-formwrap .gform_wrapper.gravity-theme .gfield_radio {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
    gap: 0.6rem 1.5rem;
    margin-top: 0.2rem;
}
.grp-formwrap .gform_wrapper.gravity-theme .gchoice {
    display: flex;
    align-items: flex-start;
    gap: 0.55rem;
}
.grp-formwrap .gform_wrapper.gravity-theme .gchoice label {
    font-size: 0.95rem;
    font-weight: 400;
    letter-spacing: normal;
    text-transform: none;
    line-height: 1.4;
    margin: 0;
    max-width: none;
    color: rgb(var(--c-ink));
    cursor: pointer;
}
.grp-section--slate .grp-formwrap .gform_wrapper.gravity-theme .gchoice label,
.grp-section--navy .grp-formwrap .gform_wrapper.gravity-theme .gchoice label {
    color: rgba(var(--c-paper), 0.85);
}
.grp-formwrap .gform_wrapper.gravity-theme .gchoice input[type="checkbox"],
.grp-formwrap .gform_wrapper.gravity-theme .gchoice input[type="radio"] {
    width: 1.1rem;
    height: 1.1rem;
    margin: 0.15rem 0 0;
    flex-shrink: 0;
    accent-color: var(--brand-primary);
    cursor: pointer;
}

/* ---- submit -------------------------------------------------------------- */
.grp-formwrap .gform_wrapper.gravity-theme .gform_footer {
    margin: 2rem 0 0;
    padding: 0;
}
/* Mirrors .grp-btn + .grp-btn--dark, the pairing the light referral panel used.
   The slate/navy override below swaps to --light, keeping each button on the
   same side of the contrast divide as its ground, per the note beside
   .grp-btn--taupe in style.css. */
.grp-formwrap .gform_wrapper.gravity-theme .gform_footer input[type="submit"],
.grp-formwrap .gform_wrapper.gravity-theme .gform_footer .gform_button {
    --btn-pad-y: 1.3em;
    --btn-pad-x: 2.4em;
    min-width: 242px;
    width: auto;
    display: inline-block;
    padding: var(--btn-pad-y) var(--btn-pad-x);
    border: 1px solid var(--brand-dark);
    border-radius: 1px;
    background-color: var(--brand-dark);
    color: rgb(var(--c-paper));
    font-family: var(--font-body);
    font-size: clamp(0.8rem, 0.95vw, 0.9rem);
    line-height: 1.2;
    font-weight: 700;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    text-align: center;
    cursor: pointer;
    transition: background-color 0.35s ease, border-color 0.35s ease, color 0.35s ease;
}
.grp-section--slate .grp-formwrap .gform_wrapper.gravity-theme .gform_footer input[type="submit"],
.grp-section--slate .grp-formwrap .gform_wrapper.gravity-theme .gform_footer .gform_button,
.grp-section--navy .grp-formwrap .gform_wrapper.gravity-theme .gform_footer input[type="submit"],
.grp-section--navy .grp-formwrap .gform_wrapper.gravity-theme .gform_footer .gform_button {
    background-color: rgb(var(--c-paper));
    border-color: rgb(var(--c-paper));
    color: var(--brand-dark);
}
.grp-formwrap .gform_wrapper.gravity-theme .gform_footer input[type="submit"]:hover,
.grp-formwrap .gform_wrapper.gravity-theme .gform_footer .gform_button:hover {
    background-color: var(--brand-primary);
    border-color: var(--brand-primary);
    color: rgb(var(--c-paper));
}
.grp-section--slate .grp-formwrap .gform_wrapper.gravity-theme .gform_footer input[type="submit"]:hover,
.grp-section--slate .grp-formwrap .gform_wrapper.gravity-theme .gform_footer .gform_button:hover,
.grp-section--navy .grp-formwrap .gform_wrapper.gravity-theme .gform_footer input[type="submit"]:hover,
.grp-section--navy .grp-formwrap .gform_wrapper.gravity-theme .gform_footer .gform_button:hover {
    background-color: rgb(var(--c-sky));
    border-color: rgb(var(--c-sky));
    color: var(--brand-dark);
}
.grp-formwrap .gform_wrapper.gravity-theme .gform_footer input[type="submit"]:focus-visible,
.grp-formwrap .gform_wrapper.gravity-theme .gform_footer .gform_button:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px rgb(var(--c-paper)), 0 0 0 4px var(--brand-dark);
}

/* ---- validation + confirmation ------------------------------------------ */
.grp-formwrap .gform_wrapper.gravity-theme .gfield_validation_message,
.grp-formwrap .gform_wrapper.gravity-theme .validation_message {
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: normal;
    text-transform: none;
    color: var(--color-error);
    background: #fff;
    border: none;
    padding: 4px 8px;
    border-radius: 6px;
}
.grp-formwrap .gform_wrapper.gravity-theme .gform_validation_errors {
    border-radius: 2px;
}
.gform_confirmation_message,
.grp-formwrap .gform_confirmation_message {
    max-width: 34rem;
    margin: 0 0 var(--gap-block);
    padding: 0.85rem 1.1rem;
    border-radius: 2px;
    font-weight: 600;
    background-color: rgba(var(--c-sky), 0.35);
    color: rgb(var(--c-ink));
}

/* Textarea needs its specificity stated the long way. The competing rule in
   style.css is:
     html body .gform_wrapper .gfield textarea:not([type=radio]):not([type=checkbox])
       :not([type=submit]):not([type=button]):not([type=image]):not([type=file])
   Each :not() contributes its argument's weight, so those six attribute
   selectors push it to (0,8,3) — above the (0,4,1) the block above lands at,
   which is why the textarea alone kept the old transparent/white-text
   treatment while the input and select picked up the new one. Restating the
   chain here reaches (0,10,1) and wins on specificity rather than !important.
   (The input rule above already carries a five-clause chain of its own, which
   is the accident that made it work first time.) */
.grp-formwrap .gform_wrapper.gravity-theme .gfield textarea:not([type="radio"]):not([type="checkbox"]):not([type="submit"]):not([type="button"]):not([type="image"]):not([type="file"]) {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    width: 100%;
    box-sizing: border-box;
    resize: vertical;
    min-height: 8rem;
    font-family: var(--font-body);
    font-size: 1rem;
    font-weight: 500;
    line-height: 1.4;
    padding: 0.5rem;
    margin: 0;
    border: 1.5px solid rgba(var(--c-ink), 0.7);
    border-radius: 2px;
    background-color: #fff;
    color: rgb(var(--c-ink));
    transition: border-color 0.25s ease, box-shadow 0.25s ease;
}
.grp-formwrap .gform_wrapper.gravity-theme .gfield textarea:not([type="radio"]):not([type="checkbox"]):not([type="submit"]):not([type="button"]):not([type="image"]):not([type="file"]):focus-visible {
    outline: none;
    border-color: var(--brand-primary);
    box-shadow: 0 0 0 3px rgba(var(--c-sky), 0.4);
}

/* Required marker on the dark panels.
   --color-error is #c02b0a, which measures 1.27:1 on the slate panel and
   2.50:1 on navy — unreadable. It only clears AA on the light grounds
   (5.13:1 on paper, 4.85:1 on the referral tint), so it stays there and the
   dark panels get the label's own paper tint at 6.53:1 instead.
   Losing the red on those panels costs nothing that mattered: Gravity Forms
   writes the word "(Required)", so the requirement is carried by the text,
   and WCAG 1.4.1 says it must not be carried by colour alone anyway. */
.grp-section--slate .grp-formwrap .gform_wrapper.gravity-theme .gfield_required,
.grp-section--navy .grp-formwrap .gform_wrapper.gravity-theme .gfield_required {
    color: rgba(var(--c-paper), 0.85);
}

/* Required marker, light grounds.
   The token (#c02b0a) computes to 4.84:1 on the referral tint and would pass,
   but it renders as #c53f21 — something upstream lightens it — which Lighthouse
   measures at 4.23:1 against #e7eaec, under the 4.5 needed at this size. GF also
   nests the span (span.gfield_required > span.gfield_required), so both levels
   are set here. #a82409 leaves headroom: 5.95:1 on the referral tint, 6.31 on
   paper, 7.19 on white. Dark panels keep the paper tint set further above. */
.grp-formwrap .gform_wrapper.gravity-theme .gfield_required,
.grp-formwrap .gform_wrapper.gravity-theme .gfield_required .gfield_required {
    color: #a82409;
}
.grp-section--slate .grp-formwrap .gform_wrapper.gravity-theme .gfield_required,
.grp-section--slate .grp-formwrap .gform_wrapper.gravity-theme .gfield_required .gfield_required,
.grp-section--navy .grp-formwrap .gform_wrapper.gravity-theme .gfield_required,
.grp-section--navy .grp-formwrap .gform_wrapper.gravity-theme .gfield_required .gfield_required {
    color: rgba(var(--c-paper), 0.85);
}

/* Helper text needs more weight than the reference specified.
   .grp-form__hint used rgba(--c-ink, 0.65), and this block inherited that — but
   the referral panel's background is itself translucent
   (rgba(197,213,231,0.25)), so the effective ground is whatever sits behind it
   and axe measures the composite as under 4.5:1 at this 13.6px / 400 size.
   0.8 clears it against every plausible ground (8.47:1 on the referral tint,
   8.84 on paper, 9.62 on white) and still reads as muted secondary text.
   This is a deliberate deviation from the 0.65 in the hand-built rules — that
   value has the same latent problem wherever it sits on a translucent panel. */
.grp-formwrap .gform_wrapper.gravity-theme .gfield_description,
.grp-formwrap .gform_wrapper.gravity-theme .gform_fileupload_rules {
    color: rgba(var(--c-ink), 0.8);
}
.grp-section--slate .grp-formwrap .gform_wrapper.gravity-theme .gfield_description,
.grp-section--slate .grp-formwrap .gform_wrapper.gravity-theme .gform_fileupload_rules,
.grp-section--navy .grp-formwrap .gform_wrapper.gravity-theme .gfield_description,
.grp-section--navy .grp-formwrap .gform_wrapper.gravity-theme .gform_fileupload_rules {
    color: rgba(var(--c-paper), 0.8);
}

/* Focus state: hold colour and background steady.
   style.css carries a :focus rule for these fields that flips them to
   transparent-with-paper-text:
     html body .gform_wrapper .gfield input:not([type=radio])…:not([type=file]):focus
       { background-color:rgba(255,255,255,0); color:rgb(var(--color-white)) }
   (--color-white resolves to --c-paper, #f1f0ee.) Six :not() clauses plus the
   :focus pseudo put it at (0,9,3), above the (0,9,1) the base field rule lands
   at — so the field was correct until you clicked into it, then went
   near-white-on-transparent while you typed and snapped back on blur. The focus
   rule further up only set border-color and box-shadow, so colour and
   background fell through to it; they are set explicitly here.
   Input arm reaches (0,11,1), select arm (0,5,1) against its (0,4,3). Both
   :focus and :focus-visible are covered so it holds however focus arrives. */
.grp-formwrap .gform_wrapper.gravity-theme .gfield input:not([type="radio"]):not([type="checkbox"]):not([type="submit"]):not([type="button"]):not([type="image"]):not([type="file"]):focus,
.grp-formwrap .gform_wrapper.gravity-theme .gfield input:not([type="radio"]):not([type="checkbox"]):not([type="submit"]):not([type="button"]):not([type="image"]):not([type="file"]):focus-visible,
.grp-formwrap .gform_wrapper.gravity-theme .gfield textarea:not([type="radio"]):not([type="checkbox"]):not([type="submit"]):not([type="button"]):not([type="image"]):not([type="file"]):focus,
.grp-formwrap .gform_wrapper.gravity-theme .gfield textarea:not([type="radio"]):not([type="checkbox"]):not([type="submit"]):not([type="button"]):not([type="image"]):not([type="file"]):focus-visible {
    background-color: #fff;
    color: rgb(var(--c-ink));
    caret-color: rgb(var(--c-ink));
    font-size: 1rem;
    padding: 0.5rem;
    border: 1.5px solid var(--brand-primary);
    border-radius: 2px;
    outline: none;
    box-shadow: 0 0 0 3px rgba(var(--c-sky), 0.4);
}
/* select keeps its chevron gutter, so its padding is stated separately rather
   than inheriting the 0.5rem above. */
.grp-formwrap .gform_wrapper.gravity-theme .gfield select:focus,
.grp-formwrap .gform_wrapper.gravity-theme .gfield select:focus-visible {
    background-color: #fff;
    color: rgb(var(--c-ink));
    font-size: 1rem;
    padding: 0.5rem;
    padding-right: 2rem;
    border: 1.5px solid var(--brand-primary);
    border-radius: 2px;
    outline: none;
    box-shadow: 0 0 0 3px rgba(var(--c-sky), 0.4);
}
/* File input focus, same treatment at its own padding. */
.grp-formwrap .gform_wrapper.gravity-theme .gfield input[type="file"]:focus,
.grp-formwrap .gform_wrapper.gravity-theme .gfield input[type="file"]:focus-visible {
    background-color: #fff;
    color: rgb(var(--c-ink));
    border: 1.5px solid var(--brand-primary);
    outline: none;
    box-shadow: 0 0 0 3px rgba(var(--c-sky), 0.4);
}
