/* ============================================================
   INTERNATIONAL DENTAL ARTS — GLOBAL STYLESHEET
   ============================================================
   Ported verbatim from the static build's two inline <style> blocks:
     - IDA Dev/index.html          lines 92–1345  (tokens, type scale, components)
     - IDA Dev/includes/header.html lines 2–332    (global mobile rules, header, nav)

   Load order matters. functions.php enqueues assets/css/tailwind.css FIRST so
   the component rules below can override Tailwind utilities.

   Rules for editing:
     - The type scale in §TYPE is canonical. Never inline font-size: clamp() on
       a heading; use .text-display / .text-h1 / .text-h2-lg / .text-h2 /
       .text-h3 / .text-h4. See .claude/build-notes.md §3 in the static repo.
     - No @font-face and no webfonts. The site is system-stack only by design.
     - Brand colors live in :root below AND in tailwind.config.js. Change both.
     - Asset URLs are theme-relative (../images/...), rewritten from the static
       build's root-absolute /assets/... paths.

   Removed during the port:
     - .pattern-overlay (defined on every static page, applied to no element,
       and its mask asset ida-squre-pattern.svg was already missing).
   ============================================================ */

/* ============================================================
   §1 TOKENS, TYPE SCALE, COMPONENTS  (from index.html)
   ============================================================ */
  :root{
    /* Brand */
    --ida-purple:        #3B3FB6;   /* exact brand purple */
    --ida-purple-bright: #6A6EE8;   /* expanded — for hover/accents on dark */
    --ida-purple-deep:   #1F2270;   /* expanded — for shadows/depth */
    --ida-orange:        #F94E00;   /* exact brand orange */
    --ida-orange-warm:   #FF8A4D;   /* expanded — softer aurora tone */
    --ida-green:         #35D52F;   /* exact brand green */
    --ida-green-soft:    #6FE56A;   /* expanded — softer for hover/glow */
    --ida-specialty-blue:#34B6E4;   /* 4th accent — from Specialty branding */
    --ida-navy-brand:    #101820;   /* exact brand dark navy */
    --ida-navy-deep:     #0C131B;   /* expanded — slight depth shift */
    --ida-navy-mid:      #141D27;   /* expanded — mid section bg */
    --ida-navy-warm:     #1A1A28;   /* expanded — warmer tone for About */
    --ida-black:         #070B11;   /* expanded — deepest band */
    /* Aurora */
    --ida-aurora-purple:  #3B3FB6;
    --ida-aurora-magenta: #6A3FB6;  /* purple→orange bridge */
    --ida-aurora-amber:   #F94E00;
    --ida-line: rgba(255,255,255,0.08);
    --ida-line-strong: rgba(255,255,255,0.16);
    --ida-text-mute: rgba(255,255,255,0.55);
    --ida-text-dim:  rgba(255,255,255,0.4);

    /* Per-hub accent — overridden inline on each hub <body>.
       Default to orange (homepage). */
    --hub-accent: var(--ida-orange);
  }
  html,body{ background: var(--ida-black); color:#fff; }
  body{
    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
    overflow-x: hidden;
  }
  .font-display{
    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
    letter-spacing: -0.035em;
    font-weight: 700;
  }
  .font-display-light{ font-weight: 300; letter-spacing: -0.035em; }
  .tracking-tightest { letter-spacing: -0.04em; }
  .tracking-display  { letter-spacing: -0.03em; }

  /* ---------- Sticky in-page anchor nav (used on /about/) ---------- */
  .anchor-nav{
    position: sticky;
    top: 72px;  /* sits just below the fixed site header */
    z-index: 40;
    background: rgba(10,14,31,0.85);
    backdrop-filter: blur(16px) saturate(140%);
    -webkit-backdrop-filter: blur(16px) saturate(140%);
    border-bottom: 1px solid rgba(255,255,255,0.08);
  }
  .anchor-nav ul{
    display: flex;
    gap: 0.25rem;
    padding: 14px 0;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .anchor-nav ul::-webkit-scrollbar{ display: none; }
  .anchor-nav a{
    display: inline-flex; align-items: center;
    padding: 8px 14px;
    border-radius: 999px;
    font-size: 11px; letter-spacing: 0.18em; font-weight: 600;
    text-transform: uppercase; white-space: nowrap;
    color: rgba(255,255,255,0.55);
    transition: color .2s ease, background .2s ease;
  }
  .anchor-nav a:hover{ color: #fff; background: rgba(255,255,255,0.06); }
  .anchor-nav a.is-active{ color: #fff; background: rgba(255,255,255,0.10); }

  /* Section anchors need scroll-margin so they land below the fixed header +
     sticky in-page nav (72px header + ~52px nav + buffer = ~140px). */
  [data-anchor-section]{ scroll-margin-top: 140px; }


  /* ---------- Tabs (cream section variant) ----------
     Pill-shaped tab triggers. Active + hover = solid orange fill, white text + icon.
     `aria-selected` drives the active state.
  */
  .tab-trigger{
    display: inline-flex; align-items: center; gap: 0.5rem;
    padding: 12px 22px;
    border-radius: 999px;
    font-size: 14px; font-weight: 600;
    color: rgba(16,24,32,0.55);
    background: transparent;
    border: 1px solid rgba(16,24,32,0.15);
    cursor: pointer;
    transition: background .2s ease, color .2s ease, border-color .2s ease;
  }
  .tab-trigger:hover,
  .tab-trigger[aria-selected="true"]{
    color: #fff;
    background: var(--ida-orange);
    border-color: var(--ida-orange);
  }
  /* When the trigger is active/hovered, its icon stroke follows currentColor → white */
  .tab-trigger:focus-visible{
    outline: 2px solid var(--ida-orange);
    outline-offset: 2px;
  }
  /* Reversed treatment: on a .section-accent host (any coloured bg) the tabs
     default to white text with a subtle white border, then flip to a solid
     white fill with accent-coloured text when hovered or selected. `var(--hub-accent)`
     resolves per-section, so this scales to green / orange / blue tabs too. */
  section.section-accent .tab-trigger{
    color: rgba(255,255,255,0.75);
    border-color: rgba(255,255,255,0.35);
  }
  section.section-accent .tab-trigger:hover,
  section.section-accent .tab-trigger[aria-selected="true"]{
    color: var(--hub-accent);
    background: #ffffff;
    border-color: #ffffff;
  }
  section.section-accent .tab-trigger:focus-visible{
    outline: 2px solid #ffffff;
  }
  /* Hidden tabpanels — using [hidden] attribute */
  .tab-panel[hidden]{ display: none; }
  /* Tab-panel CTA sits full-width at the bottom of the container on mobile /
     tablet — one big commit-action button under the steps list. On desktop it
     reverts to an inline pill under the left column's body copy via a two-row
     grid: row 1 has left/right side-by-side, row 2 puts the pill in the left
     slot while the taller right slot spans both rows. */
  .tab-panel .tab-panel-cta{
    grid-column: 1 / -1;
    justify-self: stretch;
    justify-content: center;
    width: 100%;
    margin-top: 32px;
  }
  @media (min-width: 1024px) {
    .tab-panel {
      align-items: start;
      grid-template-areas:
        "left right"
        "cta  right";
      grid-template-rows: auto 1fr;
      row-gap: 0; /* the panel's lg:gap-12 was adding 48px between rows too */
    }
    .tab-panel > div:first-child { grid-area: left; }
    .tab-panel > .tab-steps { grid-area: right; }
    .tab-panel > div.aspect-\[4\/3\] { grid-area: right; }
    .tab-panel > .tab-panel-cta {
      grid-area: cta;
      grid-column: auto;
      width: auto;
      justify-self: start;
      justify-content: center;
      align-self: start;
      margin-top: 30px;
    }
  }

  /* ---------- Widow prevention (site-wide) ----------
     text-wrap: balance on headings spreads words evenly across lines so no
     single word dangles on the last line. text-wrap: pretty on body paragraphs
     prevents a one-word last line. Modern browsers only (Chrome 114+, Safari
     17.4+, Firefox 121+); older browsers fall back to normal wrap. */
  h1, h2, h3, h4, h5, h6 { text-wrap: balance; }
  p, li { text-wrap: pretty; }

  /* ---------- Formal type scale (canonical heading sizes) ----------
     Use these classes on every heading instead of inline font-size:
       .text-display  → Page-lead moments (homepage hero, homepage final CTA)
       .text-h1       → Internal page hero, hub final CTA
       .text-h2-lg    → Featured/major section heading
       .text-h2       → Standard section heading (intro, grid, decision aid, testimonials)
       .text-h3       → Card titles, sub-section heading
       .text-h4       → Small step/inline cards
  */
  .text-display { font-size: clamp(48px, 7.6vw, 124px); line-height: 0.95; }
  .text-h1      { font-size: clamp(38px, 5vw,   76px);  line-height: 1.02; }
  .text-h2-lg   { font-size: clamp(34px, 4.2vw, 60px);  line-height: 1.05; }
  .text-h2      { font-size: clamp(28px, 3.6vw, 48px);  line-height: 1.05; }
  .text-h3      { font-size: clamp(22px, 2.4vw, 32px);  line-height: 1.15; }
  .text-h4      { font-size: clamp(16px, 1.6vw, 20px);  line-height: 1.2;  }

  /* ---------- Grain overlay (SVG turbulence) ---------- */
  .grain::before{
    content:"";
    position:absolute; inset:0;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.95  0 0 0 0 0.95  0 0 0 0 1  0 0 0 0.42 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
    background-size: 220px 220px;
    mix-blend-mode: overlay;
    opacity: 0.35;
    pointer-events:none;
    z-index: 1;
  }
  .grain-strong::before{ opacity: 0.55; }
  .grain > *{ position: relative; z-index: 2; }

  /* ---------- Aurora gradients ---------- */
  .aurora-hero{
    position:absolute; inset:-10% -10% -10% -10%;
    background:
      radial-gradient(60% 55% at var(--ax,72%) var(--ay,38%), rgba(106,63,182,0.55) 0%, rgba(106,63,182,0) 60%),
      radial-gradient(45% 50% at var(--bx,82%) var(--by,62%), rgba(249,78,0,0.48) 0%, rgba(249,78,0,0) 60%),
      radial-gradient(70% 60% at var(--cx,30%) var(--cy,55%), rgba(59,63,182,0.65) 0%, rgba(59,63,182,0) 65%),
      radial-gradient(55% 50% at 10% 10%, rgba(106,110,232,0.35) 0%, rgba(106,110,232,0) 60%);
    filter: saturate(1.05);
    will-change: transform;
  }

  /* Hero mesh-gradient shader canvas (replaces .aurora-hero on the hero) */
  #hero-shader-canvas{
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    z-index: 0;
    display: block;
    pointer-events: none;
    /* CSS fallback if WebGL unavailable */
    background:
      radial-gradient(60% 55% at 70% 40%, rgba(106,63,182,0.55) 0%, transparent 60%),
      radial-gradient(45% 50% at 82% 62%, rgba(249,78,0,0.42) 0%, transparent 60%),
      radial-gradient(70% 60% at 30% 55%, rgba(59,63,182,0.65) 0%, transparent 65%),
      radial-gradient(55% 50% at 10% 10%, rgba(106,110,232,0.30) 0%, transparent 60%);
  }
  .aurora-band{
    position:absolute; inset:0;
    background:
      radial-gradient(50% 80% at 20% 50%, rgba(59,63,182,0.55) 0%, transparent 70%),
      radial-gradient(45% 70% at 75% 50%, rgba(106,63,182,0.40) 0%, transparent 70%),
      radial-gradient(40% 80% at 95% 100%, rgba(249,78,0,0.30) 0%, transparent 70%);
  }
  .aurora-soft{
    position:absolute; inset:0;
    background:
      radial-gradient(60% 60% at 85% 30%, rgba(59,63,182,0.32) 0%, transparent 65%),
      radial-gradient(45% 55% at 12% 75%, rgba(106,110,232,0.22) 0%, transparent 65%);
  }
  .aurora-cta{
    position:absolute; inset:-10%;
    background:
      radial-gradient(45% 70% at 50% 60%, rgba(106,63,182,0.65) 0%, transparent 65%),
      radial-gradient(35% 60% at 30% 50%, rgba(59,63,182,0.75) 0%, transparent 70%),
      radial-gradient(35% 60% at 75% 55%, rgba(249,78,0,0.55) 0%, transparent 70%);
  }

  /* slow drift on aurora — set via CSS variables */
  @keyframes auroraDrift{
    0%,100%{ --ax:72%; --ay:38%; --bx:82%; --by:62%; --cx:30%; --cy:55%; }
    33%{    --ax:65%; --ay:48%; --bx:88%; --by:55%; --cx:38%; --cy:48%; }
    66%{    --ax:78%; --ay:32%; --bx:75%; --by:68%; --cx:25%; --cy:62%; }
  }
  .aurora-hero{ animation: auroraDrift 18s ease-in-out infinite; }

  /* ---------- Scroll reveals ---------- */
  .reveal{ opacity:0; transform: translateY(20px); transition: opacity .8s cubic-bezier(.16,1,.3,1), transform .8s cubic-bezier(.16,1,.3,1); }
  .reveal.in{ opacity:1; transform:none; }
  .reveal-line{ overflow:hidden; }
  .reveal-line > span{
    display:inline-block; transform: translateY(110%);
    transition: transform .8s cubic-bezier(.16,1,.3,1);
  }
  .reveal-line.in > span{ transform: translateY(0); }

  /* Above-the-fold hero content (headline/intro/CTA) must not wait on global.js —
     it's deferred behind head tracking scripts, so gating first-viewport content
     on JS cost 4-6s of Largest Contentful Paint render delay. .in still gets
     added by the reveal observer same as everywhere else; it's just a no-op here
     since the element is already at its resting state. */
  .reveal.above-fold{ opacity:1; transform:none; }
  .reveal-line.above-fold > span{ transform:none; }

  /* ---------- Frosted card ---------- */
  .glass{
    background: linear-gradient(180deg, rgba(255,255,255,0.04) 0%, rgba(255,255,255,0.015) 100%);
    border: 1px solid var(--ida-line);
    backdrop-filter: blur(14px) saturate(110%);
    -webkit-backdrop-filter: blur(14px) saturate(110%);
    transition: transform .3s cubic-bezier(.16,1,.3,1), border-color .3s ease, box-shadow .3s ease, background .3s ease;
  }
  .glass:hover{
    transform: translateY(-3px);
    border-color: rgba(106,110,232,0.45);
    box-shadow: 0 18px 60px -20px rgba(59,63,182,0.55), 0 0 0 1px rgba(106,110,232,0.15) inset;
    background: linear-gradient(180deg, rgba(106,110,232,0.05) 0%, rgba(255,255,255,0.02) 100%);
  }
  /* Process cards (#how section) — static, no hover state at all.
     Force background to stay white (matching `.section-light .glass` base) and box-shadow
     to keep the resting elevation; otherwise the .glass:hover rule's purple-tinted gradient
     bleeds through and makes the card look like it changes color on hover.
     !important is needed to beat the mobile `.glass:hover !important` reset added earlier. */
  #how .glass{ transition: none !important; }
  #how .glass:hover{
    transform: none !important;
    border-color: rgba(16,24,32,0.10) !important;
    background: #FFFFFF !important;
    box-shadow: 0 1px 0 rgba(16,24,32,0.04), 0 12px 32px -16px rgba(16,24,32,0.10) !important;
  }

  /* Scoped .glass hover variant — no outline change on hover, green drop shadow.
     Used on the Real Cases mini-story cards (Case Planning) and any future grid
     where we want a subtler hover without the purple ring. */
  .cards-green-hover .glass:hover{
    transform: translateY(-3px);
    border-color: var(--ida-line);  /* keep neutral, no purple outline */
    box-shadow: 0 18px 60px -20px rgba(53,213,47,0.55), 0 0 0 1px rgba(53,213,47,0.18) inset;
    background: linear-gradient(180deg, rgba(53,213,47,0.04) 0%, rgba(255,255,255,0.02) 100%);
  }

  /* ---------- Pill CTA ---------- */
  .pill{
    display:inline-flex; align-items:center; gap:.65rem;
    padding: 14px 22px 14px 26px;
    border-radius: 999px;
    font-size: 14px; letter-spacing: .02em; font-weight: 500;
    background: var(--ida-purple);
    color:#fff;
    transition: background .25s ease, transform .25s cubic-bezier(.16,1,.3,1), box-shadow .25s ease;
    box-shadow: 0 12px 40px -10px rgba(59,63,182,0.6);
  }
  .pill:hover{ background: var(--ida-purple-bright); box-shadow: 0 18px 48px -10px rgba(106,110,232,0.85); }
  .pill .arr{ transition: transform .25s cubic-bezier(.16,1,.3,1); }
  .pill:hover .arr{ transform: translateX(5px); }

  /* Outline variant — white text on a transparent bg with a white border.
     Used alongside the filled .pill when a secondary CTA should feel lighter
     (e.g. Book a Call next to Access Pricing). On hover the border tightens
     and a small white tint fills the pill without switching to a solid
     white slab. */
  .pill.pill--outline{
    background: transparent;
    color: #fff;
    border: 1px solid rgba(255,255,255,0.75);
    box-shadow: none;
  }
  .pill.pill--outline:hover{
    background: rgba(255,255,255,0.10);
    border-color: #ffffff;
    box-shadow: none;
  }

  /* Text link used as a secondary CTA — just an underlined label with an
     icon, no pill background. Sits inline with a filled .pill on the same
     row and reads as clearly-secondary. */
  .text-link-underline{
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 14px;
    font-weight: 500;
    letter-spacing: .02em;
    color: #fff;
    text-decoration: underline;
    text-underline-offset: 5px;
    text-decoration-thickness: 1px;
    padding: 12px 6px;
    transition: color .2s ease, text-decoration-color .2s ease;
  }
  .text-link-underline:hover{
    color: rgba(255,255,255,0.75);
  }
  .text-link-underline .arr{ transition: transform .2s cubic-bezier(.16,1,.3,1); }
  .text-link-underline:hover .arr{ transform: translate(2px, -2px); }

  /* Title-case all button text */
  .pill, .pill-ghost, .mobile-call, .mega-view-all{ text-transform: capitalize; }

  /* Highlighter marker — keyframe animation draws the bg left→right after reveal-line settles */
  @keyframes hlDraw{
    from{ background-size: 0% 100%; }
    to  { background-size: 100% 100%; }
  }
  .hl{
    display: inline-block;
    background-repeat: no-repeat;
    background-position: left center;
    background-size: 0% 100%;
    color: #fff;
    padding: 0.04em 0;
  }
  .hl-orange{ background-image: linear-gradient(var(--ida-orange), var(--ida-orange)); }
  .hl-purple{ background-image: linear-gradient(var(--ida-purple), var(--ida-purple)); }
  .hl-green { background-image: linear-gradient(var(--ida-green), var(--ida-green)); }
  .hl-blue  { background-image: linear-gradient(var(--ida-specialty-blue), var(--ida-specialty-blue)); }
  /* Per-hub highlight — color comes from --hub-accent set on <body>.
     Zero horizontal padding so adjacent punctuation (period, comma) sits
     flush against the highlighted word instead of trailing in dead space. */
  .hl-hub   {
    background-image: linear-gradient(var(--hub-accent, var(--ida-orange)), var(--hub-accent, var(--ida-orange)));
    padding: 0.04em 0;
  }

  /* When the parent reveal-line scrolls in, draw the marker */
  .reveal-line.in .hl{
    animation: hlDraw .85s cubic-bezier(.4,0,.2,1) .5s forwards;
  }
  /* On internal pages where the H1 is a single text widget (not split into
     reveal-line spans), the .hl-hub also draws when its parent .reveal fires. */
  .reveal.in .hl-hub{
    animation: hlDraw .85s cubic-bezier(.4,0,.2,1) .5s forwards;
  }

  /* ---------- Hub-page hero (full-bleed image background) ---------- */
  .hub-hero{
    position: relative;
    min-height: 80vh;
    display: flex;
    align-items: center;
    padding: 160px 0 96px;
    background-color: var(--ida-navy-deep);
    background-size: cover;
    background-position: center center;
    background-repeat: no-repeat;
    overflow: hidden;
  }
  .hub-hero::before{
    content: "";
    position: absolute; inset: 0;
    /* Dark-navy gradient overlay: 80% L → 20% R for text legibility */
    background: linear-gradient(to right, rgba(16,24,32,0.80) 0%, rgba(16,24,32,0.20) 100%);
    pointer-events: none;
  }
  .hub-hero > *{ position: relative; z-index: 1; }
  .hub-hero-content{ max-width: 72%; }
  @media (max-width: 1024px){ .hub-hero-content{ max-width: 100%; } }

  /* Hub service-card grid.
     - Override the carousel sizing (.service-card has width: clamp(280px,38vw,720px)
       intended for a 100vw flex carousel) so the cards fill their grid cells
       at every viewport. Without this, cards exceed cell width at viewports
       ≥ ~1800px and physically overlap.
     - Photo + overlay treatment matches the homepage service-card style. */
  .hub-cards .service-card{
    width: 100%;
    max-width: 100%;
  }

  /* Hub feature-image wrapper: 1:1 square (used in the "featured" block on
     each service hub — Custom Shades on Crowns, Case Planning callout on
     Implants). Image stretches to row height if the text column is taller. */
  .hub-feature-img{
    aspect-ratio: 1 / 1;
    overflow: hidden;
    border-radius: 1rem;
    height: 100%;
  }
  /* Featured-card grid (dentures protected callouts) — also square. */
  .hub-cards--featured .service-card-img{
    aspect-ratio: 1 / 1;
  }
  .hub-feature-img img{
    width: 100%; height: 100%;
    object-fit: cover; display: block;
  }

  /* Reduced-motion: skip the draw, show full marker immediately */
  @media (prefers-reduced-motion: reduce){
    .hl{ background-size: 100% 100%; }
    .reveal-line.in .hl{ animation: none; }
  }

  /* Secondary buttons: no trailing arrows */
  .pill-ghost .arr{ display: none; }

  /* Infinite logo marquee (scanner compatibility) */
  .logo-marquee{
    width: 100%;
    overflow: hidden;
    position: relative;
    padding-block: 14px;
    -webkit-mask-image: linear-gradient(90deg, transparent, black 8%, black 92%, transparent);
            mask-image: linear-gradient(90deg, transparent, black 8%, black 92%, transparent);
  }
  .logo-marquee-track{
    display: flex;
    align-items: center;
    width: max-content;
    animation: logoMarquee 24s linear infinite;
  }
  .logo-marquee:hover .logo-marquee-track{ animation-play-state: paused; }
  /* -50% works seamlessly because each item has uniform trailing margin
     (incl. the last in each set), so item 5's left edge sits exactly at
     -50% of the track width. */
  @keyframes logoMarquee{
    from{ transform: translateX(0); }
    to{ transform: translateX(var(--marquee-distance, -50%)); }
  }
  .logo-marquee-item{
    height: 42px; width: auto;
    display: block; flex: 0 0 auto;
    margin-right: 72px;
    /* Force every logo to flat white silhouette */
    filter: brightness(0) invert(1);
    opacity: 0.7;
    transition: opacity .25s ease;
  }
  .logo-marquee-item:hover{ opacity: 1; }
  @media (prefers-reduced-motion: reduce){
    .logo-marquee-track{ animation: none; }
  }

  /* Testimonial slider arrows — matches services carousel recipe, adapted for cream bg */
  .testimonial-arrows{ position:relative; }
  .testimonial-arrow{
    position:absolute; top:50%; transform: translateY(-50%);
    width:44px; height:44px; border-radius:999px;
    border:1px solid var(--ida-line-strong);
    color: rgba(16,24,32,0.72);
    background: transparent;
    display:inline-flex; align-items:center; justify-content:center;
    cursor:pointer; padding:0;
    transition: background .2s ease, border-color .2s ease, color .2s ease;
    z-index:5;
  }
  .testimonial-arrow--prev{ left:0; }
  .testimonial-arrow--next{ right:0; }
  .testimonial-arrow:hover{
    background: rgba(106,110,232,0.15);
    border-color: var(--ida-purple-bright);
    color: var(--ida-purple-bright);
  }
  @media (max-width: 900px){ .testimonial-arrow{ display:none; } }

  /* Slide states for the active testimonial */
  .testimonial-slide{ display:none; }
  .testimonial-slide.is-active{
    display:block;
    animation: testimonialFade .4s cubic-bezier(.16,1,.3,1);
  }
  @keyframes testimonialFade{
    from{ opacity:0; transform: translateY(8px); }
    to{   opacity:1; transform: translateY(0); }
  }
  @media (prefers-reduced-motion: reduce){
    .testimonial-slide.is-active{ animation: none; }
  }

  /* Featured-callout icon (replaces eyebrow on Custom Abutments / Case Planning) */
  .callout-icon{
    width: 52px; height: 52px;
    border-radius: 14px;
    border: 1px solid var(--ida-line-strong);
    background: rgba(106,110,232,0.10);
    color: var(--ida-purple-bright);
    display: inline-flex; align-items: center; justify-content: center;
    margin-bottom: 22px;
  }

  /* "Quiet" .glass variant: keeps drop shadow on hover, drops the purple outline ring + bg tint */
  .glass.glass--quiet:hover{
    border-color: var(--ida-line);
    background: linear-gradient(180deg, rgba(255,255,255,0.04) 0%, rgba(255,255,255,0.015) 100%);
    box-shadow: 0 18px 60px -20px rgba(59,63,182,0.45);
  }

  /* Callout card arrow — mirrors carousel-arrow recipe */
  .callout-arrow{
    width: 44px; height: 44px;
    border-radius: 999px;
    border: 1px solid var(--ida-line-strong);
    color: #fff;
    background: transparent;
    display: inline-flex; align-items: center; justify-content: center;
    transition: background .2s ease, border-color .2s ease, color .2s ease, transform .25s cubic-bezier(.16,1,.3,1);
  }
  .glass--quiet:hover .callout-arrow,
  .glass--quiet:focus-visible .callout-arrow{
    background: rgba(106,110,232,0.15);
    border-color: var(--ida-purple-bright);
    color: var(--ida-purple-bright);
  }

  /* Featured-callout grid hover states (Custom Abutments + Case Planning) — match .service-card */
  .callout-grid > a{ transition: transform .25s cubic-bezier(.16,1,.3,1); }
  .callout-grid > a:hover,
  .callout-grid > a:focus-visible{ transform: translateY(-3px); }

  /* Purple-bg card · chevron fills white on hover, arrow goes purple */
  .callout-card--purple:hover .callout-arrow,
  .callout-card--purple:focus-visible .callout-arrow{
    background: #fff !important;
    border-color: #fff !important;
    color: var(--ida-purple) !important;
    transform: scale(1.06);
  }

  /* White-bg card · chevron fills purple on hover, arrow goes white */
  .callout-card--white:hover .callout-arrow,
  .callout-card--white:focus-visible .callout-arrow{
    background: var(--ida-purple) !important;
    border-color: var(--ida-purple) !important;
    color: #fff !important;
    transform: scale(1.06);
  }

  /* Smaller, quieter pill — for header / dense UI contexts */
  .pill--sm{
    padding: 8px 14px 8px 16px;
    gap: .5rem;
    font-size: 13px;
    font-weight: 500;
    box-shadow: none;
    background: rgba(59,63,182,0.92);
  }
  .pill--sm:hover{
    background: var(--ida-purple-bright);
    box-shadow: 0 6px 18px -6px rgba(106,110,232,0.55);
  }
  .pill--sm svg{ width:12px; height:12px; }

  .pill-ghost{
    display:inline-flex; align-items:center; gap:.65rem;
    padding: 13px 22px;
    border-radius: 999px;
    font-size: 14px; letter-spacing: .02em; font-weight: 500;
    border: 1px solid var(--ida-line-strong);
    color:#fff;
    transition: border-color .25s ease, background .25s ease;
  }
  .pill-ghost:hover{ border-color: rgba(106,110,232,0.55); background: rgba(106,110,232,0.06); }

  /* Value-strip dividers · mobile gets horizontal between stacked rows, desktop keeps the column lines (.md\:border-l) */
  @media (max-width: 767px){
    .value-strip > * + *{
      border-top: 1px solid rgba(16,24,32,0.22);
      padding-top: 28px;
    }
    /* Drop the md:border-l on mobile so we don't get a stray left rule under the stacked layout */
    .value-strip > .md\:border-l{ border-left: none; padding-left: 0; }

    /* Tighter section padding on the value strip — collapse the 56px py-14 to ~44px */
    .section-light:has(> .value-strip){ padding-top: 44px !important; padding-bottom: 44px !important; }
    .value-strip{ padding-top: 0 !important; padding-bottom: 0 !important; }

    /* Featured callout cards (Custom Abutments + Case Planning) match service-card inner padding */
    .callout-grid > a.callout-card{ padding: 22px 22px 18px !important; }

    /* Process cards (How We Work) lose the hover outline + lift on mobile */
    .glass:hover{
      transform: none !important;
      border-color: var(--ida-line) !important;
      box-shadow: none !important;
      background: linear-gradient(180deg, rgba(255,255,255,0.04) 0%, rgba(255,255,255,0.015) 100%) !important;
    }

    /* Stats — 2×2 grid on mobile (instead of single-column stacked) */
    #case-planning .ring-stat + ::after,
    #case-planning > div > .reveal.flex.flex-wrap{
      display: grid !important;
      grid-template-columns: 1fr 1fr !important;
      gap: 18px !important;
      justify-items: center;
    }
    .ring-stat{
      width: 150px !important;
      height: 150px !important;
    }
    .ring-stat > .font-display{
      font-size: 42px !important;
    }
    /* Stat ring labels: smaller + single-line so longer labels (e.g. "Combined Technician Yrs") fit */
    .ring-stat > .text-white\/65{
      font-size: 11px !important;
      padding: 0 4px !important;
      margin-top: 8px !important;
      white-space: nowrap;
      line-height: 1.25 !important;
    }

    /* Grid columns on mobile must not expand past container — needed because
       `lg:col-span-*` has no mobile fallback and a column with un-wrappable content
       (long sentence in a <p>) shrink-wraps to that content. Force columns to wrap and
       fill the container exactly. */
    main > section .grid > div{
      min-width: 0;
      width: 100%;
    }
  }

  /* ---------- Inline arrow-text link (used in hub decision-aid + reference blocks) ---------- */
  .hub-link{
    display: inline-flex; align-items: center; gap: 0.45rem;
    transition: color .25s ease;
  }
  .hub-link .arr{
    width: 12px; height: 12px;
    transition: transform .25s cubic-bezier(.16,1,.3,1);
  }
  .hub-link:hover{ color: #fff !important; }
  .hub-link:hover .arr{ transform: translateX(4px); }

  /* ---------- Vertical gutter label ---------- */
  .gutter{
    display: none !important;
  }
  .gutter--legacy{
    position: absolute; left: 28px; top: 0;
    writing-mode: vertical-rl; transform: rotate(180deg);
    font-size: 11px; letter-spacing: 0.32em; text-transform: uppercase;
    color: var(--ida-text-mute);
    font-weight: 500;
  }
  @media (max-width: 900px){ .gutter{ display:none; } }

  /* ---------- Bracket frame ---------- */
  .bracket{ position: relative; }
  .bracket::before, .bracket::after{
    content:""; position:absolute; width:22px; height:22px;
    border-color: rgba(255,255,255,0.35); border-style:solid; border-width:0;
  }
  .bracket::before{ top:0; left:0; border-top-width:1px; border-left-width:1px; }
  .bracket::after{ bottom:0; right:0; border-bottom-width:1px; border-right-width:1px; }

  /* nav underline-from-left */
  .nav-link{ position:relative; }
  .nav-link::after{
    content:""; position:absolute; left:0; bottom:-6px; height:1px; width:100%;
    background: var(--ida-purple-bright);
    transform: scaleX(0); transform-origin: left;
    transition: transform .35s cubic-bezier(.16,1,.3,1);
  }
  .nav-link:hover::after{ transform: scaleX(1); }

  /* purple key word */
  .kw{ color: var(--ida-purple-bright); }

  /* ringed stat */
  .ring-stat{
    width: 220px; height: 220px; border-radius: 999px;
    border: 1px solid rgba(106,110,232,0.35);
    display:flex; flex-direction:column; align-items:center; justify-content:center;
    position: relative;
    transition: border-color .35s ease, transform .4s cubic-bezier(.16,1,.3,1), box-shadow .35s ease;
  }
  .ring-stat::before{
    content:""; position:absolute; inset:10px; border-radius:999px;
    border: 1px dashed rgba(106,110,232,0.15);
  }
  .ring-stat:hover{
    border-color: rgba(106,110,232,0.8);
    transform: translateY(-3px);
    box-shadow: 0 0 60px -10px rgba(106,110,232,0.5);
  }

  /* idle float on 3D objects */
  @keyframes idleFloat{
    0%,100%{ transform: translateY(0) rotate(-2deg); }
    50%   { transform: translateY(-6px) rotate(1.5deg); }
  }
  .idle-float{ animation: idleFloat 6s ease-in-out infinite; will-change: transform; }
  @keyframes idleFloat2{
    0%,100%{ transform: translateY(0) rotate(2deg); }
    50%   { transform: translateY(-5px) rotate(-1.5deg); }
  }
  .idle-float-2{ animation: idleFloat2 5.4s ease-in-out infinite; }

  /* FAQ */
  .faq-item{ border-top: 1px solid var(--ida-line); }
  .faq-item:last-child{ border-bottom: 1px solid var(--ida-line); }
  .faq-q{ display:flex; align-items:center; justify-content:space-between; width:100%; padding: 28px 0; text-align:left; gap: 24px; }
  .faq-icon{
    width: 36px; height:36px; border-radius:999px;
    border: 1px solid color-mix(in srgb, var(--hub-accent) 45%, transparent);
    display:flex; align-items:center; justify-content:center;
    color: var(--hub-accent);
    transition: transform .35s cubic-bezier(.16,1,.3,1), background .25s ease, border-color .25s ease;
    flex-shrink:0;
  }
  .faq-item.open .faq-icon{
    transform: rotate(45deg);
    background: color-mix(in srgb, var(--hub-accent) 15%, transparent);
    border-color: color-mix(in srgb, var(--hub-accent) 80%, transparent);
  }
  .faq-a{ overflow:hidden; max-height:0; transition: max-height .55s cubic-bezier(.16,1,.3,1); }
  .faq-item.open .faq-a{ max-height: 320px; }
  .faq-a-inner{ padding: 0 0 28px 0; max-width: 720px; color: var(--ida-text-mute); line-height: 1.65; }

  /* Scanner cards — the 'split' status_cards shape.
     The same white card as the three-up grid, with its title row promoted to a
     button and the connect steps in a panel beneath. It reuses .faq-icon for the
     plus, and only the open-state transform is restated, because .faq-item.open
     cannot reach a card.
     The panel height is set from scrollHeight in JS rather than a max-height
     constant: three steps measure ~200px at desktop card width and ~400px on a
     phone, so any single constant either clips the panel or makes it close slowly. */
  .scanner-card-q{ display:flex; align-items:center; justify-content:space-between; width:100%; gap: 20px; text-align:left; }
  /* Name and status tag are one group, so the tag reads as part of the heading
     instead of drifting to the far card edge. Only the plus is justified out. */
  .scanner-card-title{ display:flex; align-items:center; gap: 12px; min-width: 0; }
  .scanner-tag{
    display:inline-flex; align-items:center; flex-shrink:0;
    font-size: 10px; font-weight: 600; letter-spacing: .16em; text-transform: uppercase;
    /* --tag-ink is set inline from the item's status colour, so the fill is always
       mixed from the same hue as the text and a new status colour needs no CSS. */
    color: var(--tag-ink, var(--ida-green));
    background: color-mix(in srgb, var(--tag-ink, var(--ida-green)) 14%, transparent);
    border-radius: 999px; padding: 5px 10px 5px 11px; white-space: nowrap;
  }
  .scanner-card > h3 + p{ margin-top: 12px; }
  .scanner-card.open .faq-icon{
    transform: rotate(45deg);
    background: color-mix(in srgb, var(--hub-accent) 15%, transparent);
    border-color: color-mix(in srgb, var(--hub-accent) 80%, transparent);
  }
  .scanner-card-a{ overflow:hidden; max-height:0; transition: max-height .55s cubic-bezier(.16,1,.3,1); }
  .scanner-steps{ margin: 20px 0 2px; padding: 0; list-style: none; counter-reset: scanner-step; }
  .scanner-steps li{
    counter-increment: scanner-step;
    position: relative; padding-left: 32px;
    /* 1.55 rather than 1.65, tightened together with the gap below. The gap has to
       stay clearly wider than the leading inside a step or the wrapped steps on a
       phone read as one paragraph: at 1.55 the internal leading is ~8px and the
       gap between steps is ~16px, so the grouping survives the tightening. */
    font-size: 16px; line-height: 1.55;
  }
  /* Hairline between steps. 7px each side of the rule rather than the previous
     flat 8px gap: the divider needs symmetrical breathing room, and once a rule
     is doing the separating the whitespace no longer has to. The border spans the
     number gutter too, so it reads as one list rather than three stacked notes. */
  .scanner-steps li + li{
    margin-top: 7px;
    padding-top: 7px;
    border-top: 1px solid var(--step-line, rgba(16,24,32,0.08));
  }
  .scanner-steps li::before{
    content: counter(scanner-step) ".";
    /* Centred in the gutter rather than flush left. Vertical alignment needs no
       help: the pseudo-element inherits the 1.55 line-height factor, which puts
       its glyph centre within 0.25px of the text's first line.
       A fixed 22px box, not width:100%-of-gutter, so the digits sit between the
       card edge and the text rather than drifting into the 32px indent. */
    position: absolute; left: 0; top: 1px;
    width: 22px; text-align: center;
    font-size: 15px; font-weight: 600;
    color: var(--hub-accent);
  }

  /* The catch-all item, lifted out of the card stack into the left column. A
     notice rather than a card: tinted in the section accent and bordered, so it
     reads as an aside to the list instead of an eighth entry in it. */
  .scanner-note{
    max-width: 420px;
    padding: 18px 20px; border-radius: 16px;
    background: color-mix(in srgb, var(--hub-accent) 7%, transparent);
    border: 1px solid color-mix(in srgb, var(--hub-accent) 22%, transparent);
  }
  /* Sticky only from lg up, where the two columns exist. Below that the grid is a
     single column and pinning the heading would park it over the cards.
     The note is a child of this wrapper on desktop so the whole left block pins as
     one unit; initScannerCards moves it out to sit after the card stack on
     tablet and mobile, which is why its top margin is scoped here rather than
     living on .scanner-note, where it would double up with the grid gap. */
  /* overflow:clip rather than the section's default overflow:hidden. Both clip at
     the padding box, but only `hidden` creates a scroll container, and a scroll
     container between a sticky element and the viewport is what stops it pinning. */
  .section-clip{ overflow: clip; }
  @media (min-width: 1024px){
    .scanner-split-sticky{ position: sticky; top: 100px; }
  }
  .scanner-split-sticky .scanner-note{ margin-top: 28px; }
  .scanner-note-h{
    font-size: 17px; font-weight: 600; letter-spacing: -0.01em;
    color: var(--hub-accent);
  }
  /* Full-strength accent on every background, per Sebastian's call. On cream that
     is 3.0:1 against 15px semibold, below the 4.5:1 AA threshold for text this
     size — the earlier darkened mix sat at 4.85:1. Kept bright deliberately;
     bump the size or weight if the contrast needs revisiting. */
  .scanner-note p{ margin-top: 6px; font-size: 14px; line-height: 1.6; }
  /* Links in the note and the steps. Bold plus a hairline underline, not bold
     alone: the same sentence already carries <strong>International Dental
     Arts</strong>, so weight by itself leaves the phone number looking exactly
     like the text next to it that does nothing. The underline is what says
     clickable; the accent is the hover. */
  .scanner-note a,
  .scanner-steps a{
    font-weight: 600;
    color: inherit;
    text-decoration: underline;
    text-decoration-color: color-mix(in srgb, currentColor 35%, transparent);
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
    transition: color .2s ease, text-decoration-color .2s ease;
  }
  .scanner-note a:hover,
  .scanner-note a:focus-visible,
  .scanner-steps a:hover,
  .scanner-steps a:focus-visible{
    color: var(--hub-accent);
    text-decoration-color: var(--hub-accent);
  }
  /* The phone row is a CTA, not prose, so it opts out of the underline above.
     Selector carries .scanner-note a as well, because `.scanner-note a` alone
     outranks a lone `.scanner-note-phone` and would keep the underline. */
  .scanner-note a.scanner-note-phone{
    display: inline-flex; align-items: center; gap: 9px;
    margin-top: 14px;
    /* 14px to match the body copy, kept at 600 so it still reads as the CTA.
       The icon stays at the header's 16px: it was lifted from there deliberately
       and an icon box a little larger than its label is the normal proportion. */
    font-size: 14px; font-weight: 600;
    color: var(--phone-ink, #0F1116);
    text-decoration: none;
    transition: color .2s ease;
  }
  .scanner-note a.scanner-note-phone svg{ color: var(--hub-accent); flex-shrink: 0; }
  .scanner-note a.scanner-note-phone:hover,
  .scanner-note a.scanner-note-phone:focus-visible{ color: var(--hub-accent); text-decoration: none; }

  /* Under 640px the card is 319px wide, so a name, a tag and the plus cannot
     share one line — "Primescan / CEREC (Dentsply Sirona)" alone wants most of
     it. Drop the tag beneath the name and keep the plus at the top right. Above
     640px the card is ~700px or wider and the single row is never tight. */
  @media (max-width: 640px){
    .scanner-card-q{ align-items: flex-start; gap: 14px; }
    .scanner-card-title{ flex-direction: column; align-items: flex-start; gap: 10px; }
  }

  /* number counter prevents jitter */
  .stat-num{ font-variant-numeric: tabular-nums; }

  /* small caps spec strip / eyebrow */
  .smcaps{ font-size:11px; letter-spacing:.32em; text-transform:uppercase; color: var(--ida-orange); font-weight:500; }
  /* deeper orange on cream for WCAG contrast */
  .section-light .smcaps,
  .section-light-alt .smcaps{ color: #C73D00; }

  /* Article page accent — category eyebrow in the hero + "Share this article"
     in the body use IDA specialty blue, not the default orange. */
  body.single article > header .smcaps,
  body.single .article-share > .smcaps{ color: var(--ida-specialty-blue) !important; }

  /* Section-accent bands read too faint at the base 6% pattern opacity — bump
     to 10% so the white pattern actually shows through the coloured fill.
     Applies to the prep-guide band on service detail pages and any other
     accent-filled section with a corner pattern. */
  section.section-accent.has-corner-pattern::after,
  section.section-accent.has-corner-pattern-bl::after,
  section.section-accent.has-corner-pattern-tl::after,
  section.section-accent.has-corner-pattern-tr::after{ opacity: 0.10; }

  /* Insights AJAX filter — a subtle fade while the fetch resolves. */
  [data-posts-region] { transition: opacity .18s ease; }
  [data-posts-region].is-loading { opacity: 0.45; pointer-events: none; }
  /* opt-out modifier for eyebrows that should stay muted (e.g. hero) */
  .smcaps.smcaps--mute,
  .section-light .smcaps.smcaps--mute,
  .section-light-alt .smcaps.smcaps--mute{ color: var(--ida-text-mute); }

  /* ---------- Services full-bleed image-card carousel ---------- */
  .services-carousel{
    width: 100vw;
    margin-left: calc(50% - 50vw);
    overflow: hidden;
  }
  .services-carousel-track{
    display: flex;
    gap: 18px;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    scrollbar-width: none;
    -ms-overflow-style: none;
    padding-block: 4px;
    padding-inline: max(24px, calc((100vw - 1320px) / 2));
    scroll-padding-inline: max(24px, calc((100vw - 1320px) / 2));
  }
  .services-carousel-track::-webkit-scrollbar{ display: none; }

  .service-card{
    flex: 0 0 auto;
    width: clamp(280px, 38vw, 720px);
    scroll-snap-align: start;
    border-radius: 18px;
    overflow: hidden;
    position: relative;
    text-decoration: none;
    color: inherit;
    transition: transform .35s cubic-bezier(.16,1,.3,1);
  }
  .service-card:hover{ transform: translateY(-3px); }

  .service-card-img{
    position: relative;
    aspect-ratio: 4 / 3;
    background:
      linear-gradient(160deg, rgba(255,255,255,0.05) 0%, rgba(255,255,255,0.015) 60%, rgba(0,0,0,0.20) 100%),
      var(--ida-navy-mid);
    border-radius: 18px;
    overflow: hidden;
  }
  /* Placeholder pattern */
  .service-card-img[data-img-placeholder]::before{
    content: "";
    position: absolute; inset: 0;
    background-image: radial-gradient(rgba(255,255,255,0.08) 1px, transparent 1px);
    background-size: 18px 18px;
    opacity: 0.55;
    pointer-events: none;
  }
  .service-card-img[data-img-placeholder]::after{
    content: "Image placeholder";
    position: absolute;
    top: 50%; left: 50%; transform: translate(-50%, -50%);
    font-size: 11px; letter-spacing: 0.32em; text-transform: uppercase;
    color: rgba(255,255,255,0.28); font-weight: 500;
    pointer-events: none;
  }
  /* Real image fills the card; sits beneath text + arrow */
  .service-card-bg{
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: cover;
    object-position: center center;
    z-index: 0;
    display: block;
  }
  /* Dark veil for readability of white text over photo */
  .service-card-overlay{
    position: absolute; inset: 0;
    background:
      linear-gradient(180deg, rgba(0,0,0,0.55) 0%, rgba(0,0,0,0.0) 38%, rgba(0,0,0,0.0) 62%, rgba(0,0,0,0.40) 100%);
    z-index: 1;
    pointer-events: none;
  }

  /* Text block: heading + description stacked at top of card */
  .service-card-text{
    position: absolute;
    top: 22px; left: 26px; right: 26px;
    z-index: 2;
  }
  .service-card-label{
    display: block; margin: 0;
    font-size: clamp(20px, 2.2vw, 30px);
    font-weight: 600; color: #fff;
    line-height: 1.15; letter-spacing: -0.015em;
    text-shadow: 0 1px 14px rgba(0,0,0,0.35);
  }
  .service-card-title{
    margin: 10px 0 0;
    font-size: 13.5px; font-weight: 400;
    color: rgba(255,255,255,0.72);
    line-height: 1.5;
    letter-spacing: 0;
    text-shadow: 0 1px 6px rgba(0,0,0,0.35);
  }
  .service-card-img > .service-card-plus{ z-index: 2; }
  .service-card-plus{
    position: absolute; bottom: 22px; right: 22px;
    width: 44px; height: 44px;
    border-radius: 999px;
    background: rgba(255,255,255,0.16);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border: 1px solid rgba(255,255,255,0.22);
    color: #fff;
    display: inline-flex; align-items: center; justify-content: center;
    transition: background .25s ease, border-color .25s ease, transform .25s ease;
  }
  .service-card:hover .service-card-plus,
  .service-card:focus-visible .service-card-plus{
    background: var(--hub-accent);
    border-color: var(--hub-accent);
    transform: scale(1.06);
  }

  /* Carousel arrows */
  .carousel-arrow{
    width: 44px; height: 44px;
    border-radius: 999px;
    border: 1px solid var(--ida-line-strong);
    background: transparent;
    color: #fff;
    display: inline-flex; align-items: center; justify-content: center;
    cursor: pointer;
    transition: background .2s ease, border-color .2s ease, color .2s ease, opacity .2s ease;
    padding: 0;
  }
  .carousel-arrow:hover:not(:disabled){
    background: rgba(106,110,232,0.15);
    border-color: var(--ida-purple-bright);
    color: var(--ida-purple-bright);
  }
  .carousel-arrow:disabled{ opacity: 0.3; cursor: not-allowed; }

  /* parallax targets */
  .parallax-aurora{ will-change: transform; }
  .parallax-render{ will-change: transform; }

  /* prefers reduced motion */
  @media (prefers-reduced-motion: reduce){
    *, *::before, *::after{ animation: none !important; transition: none !important; }
    .reveal, .reveal-line > span{ opacity:1 !important; transform:none !important; }
  }

  /* selection */
  ::selection{ background: rgba(106,110,232,0.45); color:#fff; }

  /* divider line */
  .hairline{ height:1px; background: var(--ida-line); }

  /* ---------- LIGHT SECTION MODIFIER ---------- */
  /* Cream/bone background variant. Tokens shift inside .section-light. */
  .section-light,
  .section-light-alt{
    --ida-text-mute: rgba(16,24,32,0.62);
    --ida-text-dim:  rgba(16,24,32,0.42);
    --ida-line:        rgba(16,24,32,0.10);
    --ida-line-strong: rgba(16,24,32,0.20);
    --ida-purple-bright: #2A2DAE; /* darker purple for contrast on cream */
    color: #101820;
  }
  .section-light    { background: #F4F0E8 !important; }  /* warm bone — default cream */
  .section-light-alt{ background: #ECE6D8 !important; }  /* deeper bone — use when two cream sections sit adjacent so they read as distinct */
  .section-light .grain::before,
  .section-light.grain::before{ opacity: 0.18; mix-blend-mode: multiply; }
  /* Hide aurora glows in light sections */
  .section-light .aurora-band,
  .section-light .aurora-soft{ display:none; }
  /* Force any decorative absolute gradient overlays inside light sections to fade */
  .section-light > .absolute.inset-0{ opacity: 0.28 !important; mix-blend-mode: multiply; }

  /* Override the white text utilities used throughout the design */
  .section-light .text-white\/95,
  .section-light .text-white\/90,
  .section-light .text-white\/85,
  .section-light .text-white\/80{ color: #101820; }
  .section-light .text-white\/70,
  .section-light .text-white\/65{ color: rgba(16,24,32,0.72); }
  .section-light .text-white\/60,
  .section-light .text-white\/55{ color: rgba(16,24,32,0.6); }
  .section-light .text-white\/45,
  .section-light .text-white\/40{ color: rgba(16,24,32,0.45); }
  .section-light .text-white\/30{ color: rgba(16,24,32,0.32); }
  /* very-low-opacity outline numerals (e.g. "01" decorative) */
  .section-light .text-white\/\[0\.06\]{ color: rgba(16,24,32,0.07); }

  /* Glass cards become solid bone-white with a subtle outline */
  .section-light .glass{
    background: #FFFFFF;
    box-shadow: 0 1px 0 rgba(16,24,32,0.04), 0 12px 32px -16px rgba(16,24,32,0.10);
  }
  .section-light .hairline{ background: rgba(16,24,32,0.12); }
  .section-light .border-white\/10,
  .section-light .border-white\/15{ border-color: rgba(16,24,32,0.10); }

  /* Gutter label */
  .section-light .gutter{ color: rgba(16,24,32,0.55); }

  /* Pill-ghost buttons inside light sections */
  .section-light .pill-ghost{
    color: #101820;
    border-color: rgba(16,24,32,0.20);
  }
  .section-light .pill-ghost:hover{
    border-color: rgba(106,110,232,0.55);
    background: rgba(106,110,232,0.06);
  }
  /* Keep the orange .kw highlight, but ensure the green badge dot remains visible — leave it */

  /* Legacy section portrait cards: the dark navy gradients are the design — leave them, but
     soften the silhouette overlay so they read intentional on cream */
  .section-light#story .lg\:col-span-5 svg[class*="mix-blend-screen"]{ mix-blend-mode: normal; opacity: 0.5; }
  /* Testimonial avatar circles: increase border for definition on white cards */
  .section-light .glass .rounded-full{ border-color: rgba(16,24,32,0.15) !important; }

  /* nav blur */
  .nav-blur{ background: rgba(10,14,31,0.6); backdrop-filter: blur(16px) saturate(140%); -webkit-backdrop-filter: blur(16px) saturate(140%); }

  /* hide scrollbars on hero canvas */
  .crown-glow{
    position: absolute; inset:-30%;
    background: radial-gradient(50% 50% at 50% 50%, rgba(106,110,232,0.35) 0%, transparent 60%);
    filter: blur(20px);
  }

  /* skip nav (visible on focus) */
  .skip-nav{
    position:absolute; left:-9999px; top:auto; width:1px; height:1px; overflow:hidden;
  }
  .skip-nav:focus{
    position:fixed; top:12px; left:12px; width:auto; height:auto;
    padding:10px 16px; background:#fff; color:#101820; border-radius:6px;
    z-index:1000; font-size:14px;
  }

  /* ---------- Header / nav extras ---------- */
  .header-bar{ height:72px; }

  .nav-phone{
    display:inline-flex; align-items:center; gap:8px;
    font-size:13px; color:rgba(255,255,255,0.75);
    transition: color .2s ease, background-color .2s ease;
    white-space:nowrap;
  }
  .nav-phone:hover{ color: var(--ida-purple-bright); background: transparent; }
  /* Icon carries the brand purple at rest AND on hover — text is muted white
     at rest, tints purple on hover. */
  .nav-phone svg{ color: var(--ida-purple-bright); }
  /* On the solid-hero home band the shared white-on-transparent treatment
     applies a semi-transparent hover fill — override so the number and its
     icon simply tint to purple, no background. */
  body.solid-hero.home header.nav-blur:not(.is-past-hero) .nav-phone:hover{
    color: var(--ida-purple-bright) !important;
    background: transparent !important;
  }
  /* Login button on home matches the standard (sticky) hover: subtle purple
     border + purple tint background, not the plain white brighten. */
  body.solid-hero.home header.nav-blur:not(.is-past-hero) .nav-login:hover{
    color: #fff !important;
    border-color: rgba(106,110,232,0.55) !important;
    background: rgba(106,110,232,0.06) !important;
  }
  /* Over the hero on service pages: icon stays white to match the rest of the
     inverted header chrome, and hover is a subtle white-dim instead of purple. */
  body.solid-hero:not(.home) header.nav-blur:not(.is-past-hero) .nav-phone svg{
    color: #fff;
  }
  body.solid-hero:not(.home) header.nav-blur:not(.is-past-hero) .nav-phone{
    color: #fff;
  }
  body.solid-hero:not(.home) header.nav-blur:not(.is-past-hero) .nav-phone:hover{
    color: rgba(255,255,255,0.65) !important;
    background: transparent !important;
  }

  .nav-login{
    display:inline-flex; align-items:center; gap:6px;
    font-size:13px; color:rgba(255,255,255,0.75);
    padding: 6px 12px;
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 999px;
    transition: color .2s ease, border-color .2s ease, background-color .2s ease;
    white-space:nowrap;
  }
  .nav-login:hover{
    color:#fff;
    border-color: rgba(106,110,232,0.55);
    background: rgba(106,110,232,0.06);
  }
  .nav-login svg{ opacity: 0.85; }

  /* Primary nav: items + sliding hover pill */
  .primary-nav{ position:relative; }
  .nav-pill{
    position:absolute; top:50%; left:0;
    height:34px; width:0;
    transform: translate(0,-50%);
    background: rgba(106,110,232,0.14);
    border-radius:999px;
    pointer-events:none; opacity:0;
    transition: transform .35s cubic-bezier(.16,1,.3,1), width .35s cubic-bezier(.16,1,.3,1), opacity .2s ease;
    z-index:0;
  }
  .primary-nav > a, .primary-nav > .nav-mega-wrapper > a{
    position:relative; z-index:1;
    display:inline-flex; align-items:center; gap:6px;
    padding: 6px 16px; border-radius:999px;
    font-size:14px;
    color: rgba(255,255,255,0.65);
    transition: color .25s ease;
    white-space:nowrap;
  }
  .primary-nav > a:hover, .primary-nav > .nav-mega-wrapper > a:hover{ color:#fff; }
  .primary-nav .nav-link::after{ display:none; }
  .primary-nav .nav-mega-wrapper.is-open > a{ color:#fff; }


  /* Disabled nav item — keeps it visible but non-interactive (used for pages not yet built) */
  a.is-disabled,
  .nav-link.is-disabled{
    opacity: 0.4;
    cursor: default;
    pointer-events: none;
  }

  /* Active page indicator — keep text white; the .nav-pill JS parks under the active item */
  .primary-nav > a.is-active,
  .primary-nav > .nav-mega-wrapper > a.is-active{ color: #fff; }

  /* Hero scattered-pattern overlay — white tint at 6% opacity, anchored center-bottom.
     Uses ::after so it sits above the shader canvas (z:0) but below the content (z:10). */
  .has-hero-pattern::after{
    content: '';
    position: absolute; inset: 0;
    background-color: #fff;
    -webkit-mask-image: url('../images/ida-brand-pattern.svg');
            mask-image: url('../images/ida-brand-pattern.svg');
    -webkit-mask-size: 100% auto;
            mask-size: 100% auto;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: center bottom;
            mask-position: center bottom;
    pointer-events: none;
    opacity: 0.06;
    z-index: 1;
  }

  /* Corner pattern overlay (bottom-right) — white tint at 6% opacity. */
  .has-corner-pattern::after{
    content: '';
    position: absolute;
    bottom: 0; right: 0;
    width: 42%;
    aspect-ratio: 1264.9 / 1355.3;
    background-color: #fff;
    -webkit-mask-image: url('../images/ida-brand-pattern-corner.svg');
            mask-image: url('../images/ida-brand-pattern-corner.svg');
    -webkit-mask-size: contain;
            mask-size: contain;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: bottom right;
            mask-position: bottom right;
    pointer-events: none;
    opacity: 0.06;
    z-index: 1;
  }

  /* Corner pattern overlay (bottom-left variant) — reuses bottom-right SVG mirrored via scaleX(-1). */
  .has-corner-pattern-bl::after{
    content: '';
    position: absolute;
    bottom: 0; left: 0;
    width: 42%;
    aspect-ratio: 1264.9 / 1355.3;
    background-color: #fff;
    -webkit-mask-image: url('../images/ida-brand-pattern-corner.svg');
            mask-image: url('../images/ida-brand-pattern-corner.svg');
    -webkit-mask-size: contain;
            mask-size: contain;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: bottom right;
            mask-position: bottom right;
    transform: scaleX(-1);
    pointer-events: none;
    opacity: 0.06;
    z-index: 1;
  }

  /* Corner pattern overlay (top-left variant) — white tint at 6% opacity.
     Uses ::after so it doesn't collide with .grain::before on the same section. */
  .has-corner-pattern-tl::after{
    content: '';
    position: absolute;
    top: 0; left: 0;
    width: 42%;
    aspect-ratio: 1264.9 / 1355.3;
    background-color: #fff;
    -webkit-mask-image: url('../images/ida-brand-pattern-corner-top-left.svg');
            mask-image: url('../images/ida-brand-pattern-corner-top-left.svg');
    -webkit-mask-size: contain;
            mask-size: contain;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: top left;
            mask-position: top left;
    pointer-events: none;
    opacity: 0.06;
    z-index: 1;
  }

  /* Corner pattern overlay (top-right variant) — white tint at 6% opacity.
     Reuses the top-left SVG mirrored via scaleX(-1), the same trick .has-corner-pattern-bl
     uses on the bottom-right art. Referenced by the responsive width override below
     since this file was written, but never actually defined — so the 17 sections
     that ask for it got no pattern at all. */
  .has-corner-pattern-tr::after{
    content: '';
    position: absolute;
    top: 0; right: 0;
    width: 42%;
    aspect-ratio: 1264.9 / 1355.3;
    background-color: #fff;
    -webkit-mask-image: url('../images/ida-brand-pattern-corner-top-left.svg');
            mask-image: url('../images/ida-brand-pattern-corner-top-left.svg');
    -webkit-mask-size: contain;
            mask-size: contain;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: top left;
            mask-position: top left;
    transform: scaleX(-1);
    pointer-events: none;
    opacity: 0.06;
    z-index: 1;
  }
  /* Hero uses of the top-right corner pattern read too faintly at 6% against
     the deep navy gradient — bump to 11% for heroes only so section-level
     patterns keep their softer treatment. */
  .hub-hero.has-corner-pattern-tr::after { opacity: 0.11; }

  /* Gradient hero — /schedule/. The base .hub-hero lays a navy scrim over a
     background photo; with no photo to darken, that scrim is switched off and the
     .aurora-band inside supplies all the colour over the navy fill. */
  .hub-hero--gradient::before{ display: none; }
  .hub-hero--gradient > .aurora-band{ position: absolute; inset: 0; z-index: 0; }
  .hub-hero--gradient > .max-w-\[1400px\]{ position: relative; z-index: 2; }

  /* Split hero — hero_form_shortcode is set: content left, CF7 form right on lg+. */
  .hub-hero--with-form .hub-hero-content{ max-width: none; }
  .hub-hero-grid{ display: block; }
  .hub-hero-form{
    margin-top: 40px;
    background: #ffffff;
    border: 1px solid rgba(15, 17, 22, 0.08);
    border-radius: 20px;
    padding: 32px;
    box-shadow:
      0 20px 60px -20px rgba(0, 0, 0, 0.35),
      0 30px 80px -10px rgba(106, 63, 182, 0.35);
    color: #0F1116;
  }
  .hub-hero-form .wpcf7-form{ margin: 0; }
  /* CF7 input treatment for the white card: dark ink on a subtle grey field. */
  .hub-hero-form .wpcf7-form input[type="text"],
  .hub-hero-form .wpcf7-form input[type="email"],
  .hub-hero-form .wpcf7-form input[type="tel"],
  .hub-hero-form .wpcf7-form input[type="url"],
  .hub-hero-form .wpcf7-form select,
  .hub-hero-form .wpcf7-form textarea{
    background: #F4F1EA;
    border: 1px solid rgba(15, 17, 22, 0.12);
    color: #0F1116;
  }
  .hub-hero-form .wpcf7-form input::placeholder,
  .hub-hero-form .wpcf7-form textarea::placeholder{ color: rgba(15, 17, 22, 0.45); }
  .hub-hero-form .wpcf7-form input:focus,
  .hub-hero-form .wpcf7-form select:focus,
  .hub-hero-form .wpcf7-form textarea:focus{
    border-color: var(--ida-orange, #E27B27);
    outline: none;
    background: #ffffff;
  }
  .hub-hero-form .wpcf7-form select option{ background: #ffffff; color: #0F1116; }
  .hub-hero-form .wpcf7-form label{ color: #0F1116; }

  /* In-field labels — the label sits pinned at the top-left of the field and
     the placeholder is always visible below it as an example. No animation. */
  .hub-hero-form .fl-field{
    position: relative;
    display: flex; flex-direction: column;
  }
  .hub-hero-form .fl-field label{
    position: absolute;
    left: 14px;
    top: 8px;
    pointer-events: none;
    color: rgba(15, 17, 22, 0.65);
    font-size: 11px;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    font-weight: 500;
    margin: 0;
    background: transparent;
    line-height: 1;
    z-index: 1;
  }
  .hub-hero-form .fl-field .wpcf7-form-control-wrap{ display: block; }
  /* WordPress auto-wraps CF7 output in <p> and injects a <br> after the label,
     which pushes the input down and leaves the label above the field. Kill the
     margin on the <p> and hide the injected <br> so label overlays the input. */
  .hub-hero-form .fl-field > p{ margin: 0; }
  .hub-hero-form .fl-field br{ display: none; }
  .hub-hero-form .fl-field input[type="text"],
  .hub-hero-form .fl-field input[type="email"],
  .hub-hero-form .fl-field input[type="tel"],
  .hub-hero-form .fl-field textarea{
    padding: 22px 14px 10px 14px;
  }
  .hub-hero-form .fl-field input::placeholder,
  .hub-hero-form .fl-field textarea::placeholder{
    color: rgba(15, 17, 22, 0.35);
    opacity: 1;
  }
  @media (min-width: 1024px){
    .hub-hero-grid{
      display: grid;
      grid-template-columns: minmax(0, 1fr) minmax(480px, 680px);
      gap: 64px;
      align-items: start;
    }
    .hub-hero--with-form .hub-hero-content{ padding-top: 44px; }
    .hub-hero-form{ margin-top: 0; padding: 44px; }
  }

  .nav-link--mega{ cursor:pointer; }
  .nav-chev{ transition: transform .3s cubic-bezier(.16,1,.3,1); opacity:0.7; }
  .nav-mega-wrapper.is-open .nav-chev{ transform: rotate(180deg); opacity:1; }

  /* Megamenu card */
  .nav-mega-wrapper{ position:relative; }
  .megamenu{
    position:absolute; top:calc(100% + 12px); left:0;
    width:max-content; max-width: calc(100vw - 48px);
    background: rgba(15,18,28,0.96);
    backdrop-filter: blur(24px) saturate(150%);
    -webkit-backdrop-filter: blur(24px) saturate(150%);
    border:1px solid var(--ida-line-strong);
    border-radius:16px;
    padding:24px;
    box-shadow: 0 30px 80px -20px rgba(0,0,0,0.6), inset 0 0 0 1px rgba(255,255,255,0.03);
    opacity:0; visibility:hidden; transform: translateY(-8px) scale(0.985);
    transform-origin: top left;
    transition: opacity .25s ease, transform .25s ease, visibility .25s;
    pointer-events:none;
    z-index:60;
  }
  .megamenu.is-open{
    opacity:1; visibility:visible; transform: translateY(0) scale(1); pointer-events:auto;
  }
  .megamenu-grid{
    display:grid;
    grid-template-columns: repeat(4, max-content);
    gap: 28px;
  }
  .mega-col{ min-width: 200px; }
  .mega-col-title{
    display:block;
    font-size:11px; letter-spacing:0.18em; text-transform:uppercase;
    color: var(--ida-text-mute); font-weight:600;
    margin-bottom: 14px;
    transition: color .2s ease;
  }
  .mega-col-title:hover{ color:#fff; }
  /* Per-category accent on megamenu Service headings */
  .mega-col-title[href="/crowns-bridges/"]:hover       { color: var(--ida-orange) !important; }
  .mega-col-title[href="/implant-restorations/"]:hover { color: var(--ida-purple-bright) !important; }
  .mega-col-title[href="/dentures/"]:hover             { color: var(--ida-green) !important; }
  .mega-col-title[href="/nightguards/"]:hover          { color: var(--ida-specialty-blue) !important; }

  .mega-col ul{ display:flex; flex-direction:column; gap:4px; }

  .mega-item{
    display:flex; align-items:flex-start; gap:12px;
    padding: 8px; border-radius:10px;
    transition: background .2s ease;
  }
  .mega-item:hover{ background: rgba(255,255,255,0.04); }
  .mega-item-icon{
    display: none;
  }
  .mega-item:hover .mega-item-icon{
    background: rgba(106,110,232,0.18);
    border-color: rgba(106,110,232,0.55);
    color: var(--ida-purple-bright);
  }
  .mega-item-text{ display:flex; flex-direction:column; gap:2px; line-height:1.3; min-width:0; }
  .mega-item-label{ font-size:14px; color:#fff; font-weight:500; }
  .mega-item-desc{ font-size:12px; color: var(--ida-text-mute); transition: color .2s ease; white-space:nowrap; }
  .mega-item:hover .mega-item-desc{ color: rgba(255,255,255,0.78); }

  .mega-view-all{
    display:inline-block; margin-top:14px;
    font-size:12px; color: var(--ida-purple-bright);
    letter-spacing:0.04em;
  }
  .mega-view-all:hover{ color:#fff; }

  /* Narrow dropdown variant (small dropdowns like Insights) */
  .megamenu--narrow{ padding: 10px; min-width: 200px; }
  .megamenu--narrow .megamenu-list{ display:flex; flex-direction:column; gap:2px; }
  .megamenu--narrow .megamenu-list a{
    display:block;
    padding: 10px 14px;
    border-radius: 8px;
    font-size: 14px;
    color: rgba(255,255,255,0.78);
    transition: background .2s ease, color .2s ease;
  }
  .megamenu--narrow .megamenu-list a:hover{
    background: rgba(255,255,255,0.04);
    color: #fff;
  }

  @media (max-width: 1023px){ .megamenu{ display:none; } }

  /* Right-anchored variant. Default .megamenu uses left:0, which is fine for
     the primary nav on the left side of the header. For triggers sitting on
     the right side (the Login dropdown), left:0 lets the panel overflow the
     viewport; anchor it to the trigger's right edge instead. */
  .megamenu--right{ left: auto; right: 0; transform-origin: top right; }

  /* Login trigger is a <button>, not an <a>. Reset the browser button chrome
     so the shared .nav-login styling applies cleanly. */
  .nav-login--trigger{ background: transparent; border: 1px solid rgba(255,255,255,0.12); cursor: pointer; font-family: inherit; }
  .nav-login-wrapper.is-open .nav-chev{ transform: rotate(180deg); }

  /* Hamburger */
  .hamburger{
    width:36px; height:36px;
    display:inline-flex; flex-direction:column; align-items:center; justify-content:center; gap:5px;
    background:transparent; border:0; cursor:pointer; padding:0;
  }
  .hamburger span{
    display:block; width:22px; height:1.5px;
    background:#fff; border-radius:2px;
    transition: transform .3s ease, opacity .25s ease;
  }
  .hamburger.is-open span:nth-child(1){ transform: translateY(6.5px) rotate(45deg); }
  .hamburger.is-open span:nth-child(2){ opacity:0; }
  .hamburger.is-open span:nth-child(3){ transform: translateY(-6.5px) rotate(-45deg); }
  /* Hide hamburger on desktop. Inline-style block loads after tailwind.css so
     it was overriding .lg:hidden — explicit override here wins the cascade. */
  @media (min-width: 1024px){ .hamburger{ display: none; } }

  /* Mobile drawer */
  /* Top follows the header's BOTTOM edge rather than assuming it. 72px was the
     header's height when it always sat at top:0; the home page banner pushes it
     down, and the drawer stayed put and overlapped it — the first menu item
     rendered under the logo. --merger-banner-h is only set on the home page, so
     the 0px fallback keeps every other page at the original 72px. The admin bar
     shifts the header too; those variants are below. */
  .mobile-drawer{
    position:fixed; top: calc(72px + var(--merger-banner-h, 0px)); left:0; right:0; bottom:0;
    background: rgba(7,11,17,0.98);
    backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
    z-index:49;
    transform: translateX(100%);
    transition: transform .35s cubic-bezier(.16,1,.3,1);
    overflow-y:auto;
    display:flex; flex-direction:column;
  }
  /* The admin bar pushes .header-bar down by its own height, so the drawer has
     to clear that as well. Logged-in editors only, but that is who tests this. */
  body.admin-bar .mobile-drawer{ top: calc(104px + var(--merger-banner-h, 0px)); }
  @media screen and (max-width: 782px){
    body.admin-bar .mobile-drawer{ top: calc(118px + var(--merger-banner-h, 0px)); }
  }
  .mobile-drawer.is-open{ transform: translateX(0); }
  @media (min-width: 1024px){ .mobile-drawer{ display: none; } }
  .mobile-drawer-nav{ display:flex; flex-direction:column; padding: 16px 24px 12px; }
  .mobile-drawer-nav > a, .mobile-mega > summary{
    display:flex; align-items:center; justify-content:space-between;
    padding: 18px 4px; font-size: 18px; color:#fff;
    border-bottom: 1px solid var(--ida-line);
    cursor:pointer; list-style:none;
  }
  .mobile-mega > summary::-webkit-details-marker{ display:none; }
  .mobile-mega[open] > summary svg{ transform: rotate(180deg); }
  .mobile-mega svg{ transition: transform .25s ease; }
  .mobile-mega-body{ padding: 8px 0 16px; }
  .mobile-mega-all{
    display:block; padding: 12px 4px;
    font-size:14px; color: var(--ida-purple-bright);
  }
  .mobile-mega-group{ padding: 10px 0; border-top: 1px solid var(--ida-line); }
  .mobile-mega-cat{
    display:block; padding: 6px 4px;
    font-size:11px; letter-spacing:0.32em; text-transform:uppercase;
    color: var(--ida-text-mute); font-weight:500;
  }
  /* A category with nothing under it is not labelling anything — it IS the
     destination, so it should read as a nav link rather than a caps label.
     Under Services the categories head a group of sub-products and keep the
     label treatment; under For Dentists every group is a single link (For
     Dentists, Case Planning, Intraoral Scanners, Lab Forms) and those were
     being set as labels.
     :only-child is a safe proxy here because a group's children are all <a>: a
     category with sub-links has siblings, one that is the whole group does not.
     Give a category children later and it becomes a label again on its own. */
  .mobile-mega-group > .mobile-mega-cat:only-child{
    padding: 8px 4px;
    font-size: 15px;
    letter-spacing: normal;
    text-transform: none;
    font-weight: 400;
    color: rgba(255,255,255,0.85);
  }
  .mobile-mega-group > a:not(.mobile-mega-cat){
    display:block; padding: 8px 4px 8px 14px;
    font-size:15px; color: rgba(255,255,255,0.85);
  }
  .mobile-drawer-login{
    padding: 8px 24px 16px;
    border-top: 1px solid var(--ida-line);
    display:flex; flex-direction:column; gap:6px;
  }
  .mobile-drawer-login .smcaps{
    color: var(--ida-text-mute);
    margin: 8px 0 6px;
  }
  .mobile-drawer-login > a{
    padding: 10px 4px;
    font-size: 16px;
    color: rgba(255,255,255,0.85);
    transition: color .2s ease;
  }
  .mobile-drawer-login > a:hover{ color: var(--ida-orange); }

  .mobile-drawer-footer{
    margin-top:auto; padding: 24px;
    border-top: 1px solid var(--ida-line);
    display:flex; flex-direction:column; gap:12px;
  }
  .mobile-call{
    display:inline-flex; align-items:center; justify-content:center; gap:8px;
    padding: 14px; border-radius: 999px;
    border: 1px solid var(--ida-line-strong); color:#fff; font-size:15px;
  }
  body.menu-open{ overflow:hidden; }

/* ============================================================
   §2 GLOBAL MOBILE RULES, HEADER, NAV, DRAWER  (from header.html)
   ============================================================ */
  /* Global · prevent horizontal scroll caused by off-canvas mobile drawer (fixed + translateX(100%)).
     Use `overflow-x: clip` (not `hidden`) so `position: sticky` descendants keep working — `hidden`
     creates a scroll container that breaks sticky positioning across the page. */
  html, body{ overflow-x: clip; }

  /* Mobile: hide phone / login / Schedule pill below lg (1024px). Hamburger handles all nav on mobile.
     Uses !important because .pill / .nav-phone / .nav-login base styles set `display: inline-flex`
     in per-page CSS, which loads AFTER tailwind.css and overrides the .hidden utility. */
  @media (max-width: 1023px){
    header .nav-phone,
    header .nav-login,
    header .pill.pill--sm{ display: none !important; }
  }

  /* Mobile drawer item polish (loaded after per-page CSS, so wins the cascade) */
  /* 1. Hover state — primary items, mega summaries, sub-items all shift to accent on hover */
  .mobile-drawer-nav > a,
  .mobile-mega > summary,
  .mobile-mega-group > a{ transition: color .2s ease; }
  .mobile-drawer-nav > a:hover,
  .mobile-mega > summary:hover,
  .mobile-mega-group > a:hover{ color: var(--ida-orange) !important; }

  /* 2. Sub-items align flush with primary nav items (drop the 14px left indent) */
  .mobile-mega-group > a:not(.mobile-mega-cat){ padding-left: 4px !important; }

  /* 3. Remove secondary line separators between sub-menu groups */
  .mobile-mega-group{ border-top: none !important; }

  /* ===========================================================
     IDA mobile conventions (recurring rules — apply site-wide)
     =========================================================== */
  @media (max-width: 768px){

    /* RULE 1 · all pill buttons full-width on mobile, content centered */
    .pill, .pill-ghost, .pill.pill--accent{
      width: 100% !important;
      justify-content: center !important;
      justify-self: stretch !important;
    }

    /* RULE 2 · section headings left-justified on mobile (unless overridden per page).
       Excludes `.hub-hero` — heroes keep their centered layout. */
    main > section:not(.hub-hero) .text-center,
    main > section:not(.hub-hero) .text-center h1,
    main > section:not(.hub-hero) .text-center h2,
    main > section:not(.hub-hero) .text-center h3,
    main > section:not(.hub-hero) .text-center p{ text-align: left !important; }
    main > section:not(.hub-hero) .text-center{ margin-left: 0 !important; margin-right: 0 !important; }

    /* RULE 3 · corner pattern overlays scale up to 75% on mobile (was 42% desktop) */
    .has-corner-pattern::after,
    .has-corner-pattern-tr::after,
    .has-corner-pattern-tl::after,
    .has-corner-pattern-bl::after{ width: 75% !important; }

    /* RULE 4 · in image+text sections, the IMAGE COLUMN ALWAYS COMES FIRST on mobile.
       Catches: .hub-feature-img wrappers, direct <img>/<picture>/<figure> children,
       and image columns where the image is wrapped one level deep in a <a> link. */
    main > section .grid > div:has(.hub-feature-img),
    main > section .grid > div:has(> img),
    main > section .grid > div:has(> picture),
    main > section .grid > div:has(> figure),
    main > section .grid > div:has(> a > img){ order: -1; }

    /* RULE 5 · section top/bottom padding -20px on mobile. Heroes are excluded
       and keep their full padding: .hub-hero on the internal pages, and
       .landing-hero, which is the same kind of band on the ad landing page.
       Without the exclusion this !important flattened its 152px top to 92px and
       the headline sat under the fixed header. */
    main > section:not(.hub-hero):not(.landing-hero){
      padding-top: 92px !important;
      padding-bottom: 92px !important;
    }

    /* RULE 9 · gradient treatments (aurora-band / aurora-soft / aurora-cta) must NOT warp on mobile.
       Cause: the desktop gradients use percentage-sized ellipses ("50% 80% at 20% 50%"). On a
       tall section the vertical % blows the ellipse into a smeared column.
       Fix: redefine with FIXED-PIXEL CIRCLES anchored at percentage positions. The element
       still covers the full section (`inset: 0`) — each colored blob stays round, reads as
       an atmospheric glow, and the gradient scales correctly regardless of section height.
       Apply this pattern to any new gradient overlay introduced site-wide. */
    .aurora-band{
      background:
        radial-gradient(circle 360px at 20% 12%, rgba(59,63,182,0.55) 0%, transparent 70%),
        radial-gradient(circle 320px at 75% 45%, rgba(106,63,182,0.40) 0%, transparent 70%),
        radial-gradient(circle 380px at 95% 90%, rgba(249,78,0,0.30) 0%, transparent 70%) !important;
    }
    .aurora-soft{
      background:
        radial-gradient(circle 340px at 85% 12%, rgba(59,63,182,0.32) 0%, transparent 65%),
        radial-gradient(circle 300px at 12% 60%, rgba(106,110,232,0.22) 0%, transparent 65%) !important;
    }
    .aurora-cta{
      background:
        radial-gradient(circle 340px at 50% 30%, rgba(106,63,182,0.65) 0%, transparent 65%),
        radial-gradient(circle 300px at 25% 65%, rgba(59,63,182,0.75) 0%, transparent 70%),
        radial-gradient(circle 320px at 80% 88%, rgba(249,78,0,0.45) 0%, transparent 65%) !important;
    }

    /* RULE 6 · hub-hero h1 highlight (`.hl.hl-hub`) keeps its accent treatment on mobile.
       (Previous version dropped the background — restored per Sebastian's request so the
       highlight reads on core-service hero pages.) */

    /* RULE 7 · arrow-link + pill pairing on mobile.
       - When a flex container holds BOTH a .pill and a .arrow-link, switch to column.
       - The pill is full-width (rule 1) so the arrow-link stacks below it, horizontally centered. */
    :where(div, section, nav, ul, li):has(> .pill):has(> .arrow-link){
      flex-direction: column !important;
      align-items: center !important;
    }
    :where(div, section, nav, ul, li):has(> .pill) > .arrow-link{
      align-self: center !important;
      margin-left: auto;
      margin-right: auto;
    }

    /* RULE 8 · standalone arrow-link follows content alignment on mobile.
       - Default: left-justified (already set via base `.arrow-link { align-self: flex-start; width: fit-content }`)
       - Inside a centered content block (`.text-center`, `.justify-center`, `.items-center`):
         arrow-link centers with the content.
       Note: RULE 2 forces `text-align: left` on `.text-center` containers (heading-left rule),
       so inline-level centering doesn't work. We promote the arrow-link to `display: flex`
       (block-level) + `margin: 0 auto` so it horizontally centers regardless of parent text-align. */
    .text-center .arrow-link,
    [class*="text-center"] > .arrow-link,
    [class*="items-center"] > .arrow-link:not(:has(~ .pill)),
    [class*="justify-center"] > .arrow-link:not(:has(~ .pill)){
      display: flex !important;
      align-self: center !important;
      margin-left: auto !important;
      margin-right: auto !important;
    }
  }

  /* Reliable responsive show/hide utilities — use these instead of Tailwind .hidden when the
     target has a base `display: inline-flex` or similar (e.g. .pill, .pill-ghost), since
     Tailwind's .hidden loses to per-page CSS without !important. */
  @media (max-width: 767px){ .desktop-only{ display: none !important; } }
  @media (min-width: 768px){ .mobile-only{  display: none !important; } }

  /* ===========================================================
     Solid-color hero variant · used on sub-service pages
     `.hub-hero--solid` swaps the bg-image hero for a flat accent fill, with
     the brand corner-pattern overlay anchoring the bottom-right corner.
     =========================================================== */
  .hub-hero.hub-hero--solid::before{ display: none; }
  .hub-hero.hub-hero--solid{
    background-color: var(--hub-accent) !important;
    background-image: none !important;
  }
  .hub-hero.hub-hero--solid .reveal.smcaps{ color: rgba(255,255,255,0.85) !important; }
  /* Hero CTA pill · white fill + accent text · hover navy fill + white text */
  .hub-hero.hub-hero--solid .pill{
    background: #fff;
    color: var(--hub-accent);
    box-shadow: 0 12px 40px -10px rgba(0,0,0,0.25);
  }
  .hub-hero.hub-hero--solid .pill:hover{
    background: var(--ida-navy-deep);
    color: #fff;
    box-shadow: 0 18px 48px -10px rgba(0,0,0,0.45);
  }
  /* Accent-bg sections: text goes white on the orange fill. */
  section.section-accent h2,
  section.section-accent h3,
  section.section-accent h1{ color: #fff !important; }
  section.section-accent .smcaps{ color: rgba(255,255,255,0.85) !important; }
  section.section-accent p,
  section.section-accent .text-body,
  section.section-accent > .ida-container > * > div{ color: rgba(255,255,255,0.92); }
  /* Same treatment on section-accent bands: white pill w/ hover to navy. */
  section.section-accent .pill{
    background: #fff;
    color: var(--hub-accent);
    box-shadow: 0 12px 40px -10px rgba(0,0,0,0.25);
  }
  section.section-accent .pill:hover{
    background: var(--ida-navy-deep);
    color: #fff;
    box-shadow: 0 18px 48px -10px rgba(0,0,0,0.45);
  }
  /* Tab-panel content sits on its own white card, so the section-accent
     white-text / reversed-pill rules above should NOT reach inside it —
     revert headings, eyebrows, body copy and CTAs to their light-card
     treatment. Scoped to .tab-panel-shell (the white rounded card that wraps
     every tab panel), so this only affects tab content, not other section
     children. */
  section.section-accent .tab-panel-shell h1,
  section.section-accent .tab-panel-shell h2,
  section.section-accent .tab-panel-shell h3{ color: #0F1116 !important; }
  section.section-accent .tab-panel-shell .smcaps{ color: var(--hub-accent) !important; }
  section.section-accent .tab-panel-shell p,
  section.section-accent .tab-panel-shell .text-body,
  section.section-accent .tab-panel-shell > * > div{ color: rgba(16,24,32,0.72); }
  section.section-accent .tab-panel-shell .pill{
    background: var(--ida-purple);
    color: #fff;
    box-shadow: 0 12px 40px -12px rgba(59,63,182,0.55);
  }
  section.section-accent .tab-panel-shell .pill:hover{
    background: var(--ida-purple-bright);
    color: #fff;
    box-shadow: 0 18px 48px -10px rgba(106,110,232,0.85);
  }
  /* Corner-pattern BL overlay (flipped — anchors the bottom-left) */
  .has-corner-pattern-bl::after{
    content: '';
    position: absolute;
    bottom: 0; left: 0;
    width: 42%;
    aspect-ratio: 1264.9 / 1355.3;
    background-color: #fff;
    -webkit-mask-image: url('../images/ida-brand-pattern-corner.svg');
            mask-image: url('../images/ida-brand-pattern-corner.svg');
    -webkit-mask-size: contain;          mask-size: contain;
    -webkit-mask-repeat: no-repeat;      mask-repeat: no-repeat;
    -webkit-mask-position: bottom left;  mask-position: bottom left;
    transform: scaleX(-1);
    pointer-events: none;
    opacity: 0.14;
    z-index: 1;
  }
  /* Ensure hero content (heading, copy, CTA pill) sits ABOVE the corner-pattern overlay.
     The pattern uses z-index: 1 absolutely-positioned ::after — without this, the pill
     CTA can render behind the pattern on solid sub-service heroes. */
  .hub-hero > .max-w-\[1400px\],
  .hub-hero > div{ position: relative; z-index: 2; }

  /* Corner-pattern BR overlay (anchors the bottom-right corner of solid heroes) */
  .has-corner-pattern::after{
    content: '';
    position: absolute;
    bottom: 0; right: 0;
    width: 42%;
    aspect-ratio: 1264.9 / 1355.3;
    background-color: #fff;
    -webkit-mask-image: url('../images/ida-brand-pattern-corner.svg');
            mask-image: url('../images/ida-brand-pattern-corner.svg');
    -webkit-mask-size: contain;
            mask-size: contain;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: bottom right;
            mask-position: bottom right;
    pointer-events: none;
    opacity: 0.14;
    z-index: 1;
  }

  /* ===========================================================
     Alt header treatment · body.solid-hero
     For sub-service pages with a solid-color (`hub-hero--solid`) hero.
     Header floats transparent over the hero, all chrome inverts to white.
     Once scrolled past the hero, header.is-past-hero adds the normal nav-blur
     background back, and chrome reverts to the standard dark/branded styling.
     Toggled by IntersectionObserver in the script at the bottom of this partial.
     =========================================================== */
  /* Smooth transitions between the two states */
  body.solid-hero header.nav-blur,
  body.solid-hero header.nav-blur img[alt*="International Dental Arts"],
  body.solid-hero header.nav-blur .nav-link,
  body.solid-hero header.nav-blur .nav-phone,
  body.solid-hero header.nav-blur .nav-login,
  body.solid-hero header.nav-blur .pill.pill--sm,
  body.solid-hero header.nav-blur .hamburger span{
    transition: background .25s ease, border-color .25s ease, color .25s ease, filter .25s ease, backdrop-filter .25s ease;
  }

  /* State 1: OVER the hero · transparent header, all chrome white */
  body.solid-hero header.nav-blur:not(.is-past-hero){
    background: transparent !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    border-bottom: none !important;
  }
  body.solid-hero:not(.home) header.nav-blur:not(.is-past-hero) img[alt*="International Dental Arts"]{
    filter: brightness(0) invert(1);
  }
  body.solid-hero header.nav-blur:not(.is-past-hero) .nav-link{ color: #fff; }
  body.solid-hero header.nav-blur:not(.is-past-hero) .nav-pill{ background: rgba(255,255,255,0.16) !important; }
  body.solid-hero header.nav-blur:not(.is-past-hero) .nav-phone,
  body.solid-hero header.nav-blur:not(.is-past-hero) .nav-login{
    color: #fff;
    border-color: rgba(255,255,255,0.32) !important;
  }
  body.solid-hero header.nav-blur:not(.is-past-hero) .nav-phone:hover,
  body.solid-hero header.nav-blur:not(.is-past-hero) .nav-login:hover{
    border-color: rgba(255,255,255,0.65) !important;
    background: rgba(255,255,255,0.06);
  }
  body.solid-hero:not(.home) header.nav-blur:not(.is-past-hero) .pill.pill--sm{
    background: transparent !important;
    border: 1px solid rgba(255,255,255,0.55);
    color: #fff !important;
    box-shadow: none !important;
  }
  body.solid-hero:not(.home) header.nav-blur:not(.is-past-hero) .pill.pill--sm:hover{
    background: #fff !important;
    color: var(--hub-accent) !important;
    border-color: #fff;
  }
  body.solid-hero header.nav-blur:not(.is-past-hero) .hamburger span{ background: #fff !important; }

  /* State 2: SCROLLED past hero · standard nav-blur background, default chrome.
     Nothing to override — the base .nav-blur styles take effect because the
     :not(.is-past-hero) selectors no longer match. */

  /* ===========================================================
     Standard inline arrow-link · accent color · underline grows on hover · arrow shifts right.
     Use this for secondary CTAs and inline "read more" links anywhere on the site.
     =========================================================== */
  .arrow-link{
    display: inline-flex; align-items: center; gap: 0.55rem;
    font-size: 15px; font-weight: 500;
    letter-spacing: -0.005em;
    border-bottom: 1px solid transparent;
    padding-bottom: 2px;
    transition: opacity .2s ease, border-color .2s ease;
    /* Stop the underline from stretching to full container width when the link
       is a flex item (e.g. card columns) — flex items blockify `inline-flex`. */
    align-self: flex-start;
    width: fit-content;
  }
  .arrow-link .arrow-link-arr{ transition: transform .25s cubic-bezier(.16,1,.3,1); }
  .arrow-link:hover{ border-bottom-color: currentColor; }
  .arrow-link:hover .arrow-link-arr{ transform: translateX(5px); }

  /* When .arrow-link carries .mx-auto, promote to block-flex so margin: 0 auto centers it
     (inline-flex margin-auto doesn't center inline-level boxes). */
  .arrow-link.mx-auto{ display: flex; }

  /* RULE · whenever an .arrow-link sits next to a .pill in the same flex container,
     the pair must be cross-axis centered (vertical-center the underline link with the pill). */
  :where(div, section, nav, ul, li):has(> .pill):has(> .arrow-link){
    align-items: center;
  }
  /* And the arrow-link itself overrides its default `align-self: flex-start` in that context. */
  :where(div, section, nav, ul, li):has(> .pill) > .arrow-link,
  :where(div, section, nav, ul, li):has(> .arrow-link) > .pill ~ .arrow-link,
  :where(div, section, nav, ul, li):has(> .pill) > .arrow-link ~ .pill{
    align-self: center;
  }

  /* ===========================================================
     section-light-alt — extend the same text-color overrides
     that section-light gets (per-page CSS only targets .section-light).
     =========================================================== */
  .section-light-alt .text-white\/95,
  .section-light-alt .text-white\/90,
  .section-light-alt .text-white\/85,
  .section-light-alt .text-white\/80{ color: #101820; }
  .section-light-alt .text-white\/75,
  .section-light-alt .text-white\/70,
  .section-light-alt .text-white\/65{ color: rgba(16,24,32,0.72); }
  .section-light-alt .text-white\/60,
  .section-light-alt .text-white\/55{ color: rgba(16,24,32,0.6); }
  .section-light-alt .text-white\/45,
  .section-light-alt .text-white\/40{ color: rgba(16,24,32,0.45); }
  .section-light-alt .text-white\/30{ color: rgba(16,24,32,0.32); }
  /* keep deep-orange smcaps + hide aurora glows for parity with section-light */
  .section-light-alt .aurora-band,
  .section-light-alt .aurora-soft{ display: none; }
  /* glass cards solid-white on dark cream */
  .section-light-alt .glass{
    background: #fff;
  }

  /* Responsive border-white variants also need the cream remap (sm:/md:/lg: prefixes) */
  .section-light .md\:border-white\/10,
  .section-light .lg\:border-white\/10,
  .section-light .md\:border-white\/15,
  .section-light .lg\:border-white\/15,
  .section-light-alt .md\:border-white\/10,
  .section-light-alt .lg\:border-white\/10,
  .section-light-alt .md\:border-white\/15,
  .section-light-alt .lg\:border-white\/15{ border-color: rgba(16,24,32,0.22); }

/* ============================================================
   WORDPRESS-SPECIFIC ADDITIONS
   Everything below this line has no counterpart in the static build.
   ============================================================ */

/* ── Admin bar ──────────────────────────────────────────────────────────
   The site header is position:fixed at top:0, so the 32px admin bar would
   overlap it for logged-in editors. */
body.admin-bar .header-bar { top: 32px; }
@media screen and (max-width: 782px) {
  body.admin-bar .header-bar { top: 46px; }
}

/* ── Skip link ──────────────────────────────────────────────────────────
   Visually hidden until focused. First element in <body>. */
.skip-nav {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  padding: 12px 20px;
  background: var(--ida-orange);
  color: #fff;
  font-weight: 700;
  text-decoration: none;
}
.skip-nav:focus {
  left: 0;
  outline: 3px solid #fff;
  outline-offset: -3px;
}

/* ── Visible focus for keyboard users ───────────────────────────────────
   The static build relied on browser defaults, which the dark backgrounds
   made nearly invisible. */
:focus-visible {
  outline: 3px solid var(--ida-specialty-blue);
  outline-offset: 2px;
}
.section-light :focus-visible {
  outline-color: var(--ida-purple);
}

/* ── .prose — post and event body content ───────────────────────────────
   Styles raw editor HTML. The static posts inconsistently applied utility
   classes to their body headings; in WordPress the editor emits bare tags,
   so these rules carry the whole burden. Matches the static .prose block. */
.prose { max-width: 720px; }
.prose > * + * { margin-top: 1.25em; }
.prose p { font-size: 17px; line-height: 1.75; color: rgba(255,255,255,0.78); }
.prose h2 {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 700;
  letter-spacing: -0.03em;
  font-size: clamp(24px, 2.6vw, 34px);
  line-height: 1.15;
  margin-top: 2em;
  color: #fff;
}
.prose h3 {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 700;
  letter-spacing: -0.02em;
  font-size: clamp(19px, 2vw, 24px);
  line-height: 1.25;
  margin-top: 1.75em;
  color: #fff;
}
.prose ul, .prose ol { padding-left: 1.35em; }
.prose ul { list-style: disc; }
.prose ol { list-style: decimal; }
.prose li { margin-top: 0.5em; line-height: 1.7; color: rgba(255,255,255,0.78); }
.prose li::marker { color: var(--hub-accent); }
.prose strong { color: #fff; font-weight: 700; }
.prose a {
  color: var(--hub-accent);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.prose a:hover { text-decoration-thickness: 2px; }
.prose blockquote {
  border-left: 3px solid var(--hub-accent);
  padding-left: 1.25em;
  font-size: 19px;
  line-height: 1.6;
  color: #fff;
}
.prose img {
  max-width: 100%;
  height: auto;
  border-radius: 12px;
}
.prose figcaption {
  font-size: 13px;
  color: var(--ida-text-dim);
  margin-top: 0.6em;
}
/* Cream-background variant, for legal/policy pages. */
.section-light .prose p,
.section-light .prose li { color: rgba(16,24,32,0.78); }
.section-light .prose h2,
.section-light .prose h3,
.section-light .prose strong,
.section-light .prose blockquote { color: var(--ida-navy-brand); }

/* ── WordPress core alignment + caption classes ─────────────────────────*/
.alignleft  { float: left;  margin: 0 1.5em 1em 0; }
.alignright { float: right; margin: 0 0 1em 1.5em; }
.aligncenter { display: block; margin-left: auto; margin-right: auto; }
.alignwide, .alignfull { max-width: none; }
.wp-caption { max-width: 100%; }
.wp-caption-text { font-size: 13px; color: var(--ida-text-dim); }
.screen-reader-text {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0,0,0,0);
  white-space: nowrap;
  border: 0;
}

/* ── Contact Form 7 ─────────────────────────────────────────────────────
   The static build used four hand-rolled PHP-POST forms. CF7 replaces them,
   so its output has to inherit the same input styling. Field markup differs
   (CF7 wraps every input in a <span class="wpcf7-form-control-wrap">), which
   is why these rules are not just the static form selectors. */
.wpcf7-form .wpcf7-form-control-wrap { display: block; }
.wpcf7-form input[type="text"],
.wpcf7-form input[type="email"],
.wpcf7-form input[type="tel"],
.wpcf7-form input[type="url"],
.wpcf7-form select,
.wpcf7-form textarea {
  width: 100%;
  background: rgba(255,255,255,0.05);
  border: 1px solid var(--ida-line-strong);
  border-radius: 10px;
  padding: 14px 16px;
  color: #fff;
  font-size: 15px;
  font-family: inherit;
  transition: border-color 180ms ease, background 180ms ease;
}
.wpcf7-form textarea { min-height: 120px; resize: vertical; }
.wpcf7-form input::placeholder,
.wpcf7-form textarea::placeholder { color: var(--ida-text-dim); }
.wpcf7-form input:focus,
.wpcf7-form select:focus,
.wpcf7-form textarea:focus {
  outline: none;
  border-color: var(--hub-accent);
  background: rgba(255,255,255,0.08);
}
.wpcf7-form select option { background: var(--ida-navy-brand); color: #fff; }

/* Radio and checkbox groups — the schedule form's call-window fieldset. */
/* Horizontal, wrapping, with the source's own gaps. This was `display: grid` with a
   10px gap — a vertical stack, where the source lays the call-window and start-with
   options out in a wrapping row at `gap: 0.5rem 1.75rem`. Nothing rendered these until
   now, because neither form had radios at all: both shipped as generic contact forms. */
.wpcf7-form .wpcf7-radio,
.wpcf7-form .wpcf7-checkbox {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.75rem;
}
.wpcf7-form .wpcf7-list-item { margin: 0; }
.wpcf7-form .wpcf7-list-item label {
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  font-size: 15px;
}
.wpcf7-form input[type="radio"],
.wpcf7-form input[type="checkbox"] { accent-color: var(--hub-accent); width: 18px; height: 18px; }

/* Submit — reuses the .pill treatment. */
.wpcf7-form input[type="submit"] {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: var(--hub-accent);
  color: #fff;
  border: 0;
  border-radius: 999px;
  padding: 15px 30px;
  font-weight: 700;
  font-size: 15px;
  letter-spacing: -0.01em;
  cursor: pointer;
  transition: transform 180ms ease, filter 180ms ease;
}
.wpcf7-form input[type="submit"]:hover { filter: brightness(1.08); transform: translateY(-1px); }
.wpcf7-form input[type="submit"]:active { transform: translateY(0); }

/* Visually hidden, still announced. The source labels every form field this way and
   lets the placeholder carry the visible cue — and `.sr-only` was NOT COMPILED anywhere,
   so the one label already using it was showing too. A placeholder alone is not a label:
   it disappears on focus and is not reliably announced, so these stay as real <label for>
   elements rather than being deleted. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

/* ── Forms on a LIGHT section ────────────────────────────────────────────────
   Every CF7 rule above is written for a dark background: white text on a 5%-white
   fill with a light border. All THREE page forms — /contact/, /schedule/ and
   /become-a-client/ — sit inside `.section-light`, so they were rendering white text
   on a near-white card. Only the footer newsletter is genuinely on dark, which is why
   the dark base stays.

   Values below are the source's own, read off its inline styles rather than eyeballed:
     input/textarea   background rgba(16,24,32,0.03) · border rgba(16,24,32,0.12)
                      colour #0F1116 · padding 12px 16px · radius 8px · 14px
     legend           13px, rgba(16,24,32,0.65), 12px below
     radio row        14px, rgba(16,24,32,0.85), gap 0.5rem 1.75rem
     footnote         12px, rgba(16,24,32,0.50), centred

   ONE DELIBERATE DEPARTURE, listed: the source gives selects `py-3` with no `px-4`,
   and Tailwind's preflight zeroes form-control padding — so in the reference a select's
   text sits flush against its own left border while the inputs beside it have 16px.
   That is a defect rather than a decision, so selects get the same 16px here. Say the
   word and it becomes a one-line change back. */
.section-light .wpcf7-form input[type="text"],
.section-light .wpcf7-form input[type="email"],
.section-light .wpcf7-form input[type="tel"],
.section-light .wpcf7-form input[type="url"],
.section-light .wpcf7-form select,
.section-light .wpcf7-form textarea {
  background: rgba(16,24,32,0.03);
  border: 1px solid rgba(16,24,32,0.12);
  border-radius: 8px;
  padding: 12px 16px;
  color: #0F1116;
  font-size: 14px;
}
.section-light .wpcf7-form input::placeholder,
.section-light .wpcf7-form textarea::placeholder { color: rgba(16,24,32,0.45); }
.section-light .wpcf7-form input:focus,
.section-light .wpcf7-form select:focus,
.section-light .wpcf7-form textarea:focus {
  border-color: var(--hub-accent);
  background: rgba(16,24,32,0.05);
}
.section-light .wpcf7-form select option { background: #fff; color: #0F1116; }

.section-light .ida-fieldset legend {
  font-size: 13px;
  color: rgba(16,24,32,0.65);
  margin-bottom: 0.75rem;
}
.section-light .wpcf7-form .wpcf7-radio,
.section-light .wpcf7-form .wpcf7-checkbox { font-size: 14px; color: rgba(16,24,32,0.85); }
.section-light .wpcf7-form .wpcf7-list-item label { font-size: 14px; gap: 0.5rem; }

/* The submit is a pill spanning both columns and centred, as the source has it. */
/* CF7 runs the form through wpautop, so it wraps the submit in its own <p>. That <p>
   carries the theme's paragraph margins and pushed everything below it down — the note
   sat ~47px under the button against the source's 8. Zeroed here rather than fighting
   wpautop, which would mangle the rest of the markup. */
.ida-fg-2 .wpcf7-submit-row { grid-column: 1 / -1; display: flex; justify-content: center; margin-top: 0.5rem; }
.ida-fg-2 .wpcf7-submit-row p { margin: 0; }
/* Left-align the submit button inside the hero form card. */
.hub-hero-form .ida-fg-2 .wpcf7-submit-row { justify-content: flex-start; }

/* CF7 always emits a spinner and only makes it VISIBLE while submitting — but it still
   occupies 24px of inline space beside the button the rest of the time, which the source
   has no equivalent for. Taken out of flow until the form is actually submitting. */
.wpcf7-form:not(.submitting) .wpcf7-spinner { display: none; }
/* The note the source puts INSIDE the form grid at mt-2. Rendered after </form> it
   also inherited the form's 1rem bottom margin, making the gap ~32px against the
   source's 8 — hence the negative pull-up, which lands it exactly 8px under the
   submit row wherever it is in the DOM. */
.ida-form-note {
  grid-column: 1 / -1;
  margin-top: 0.5rem;
  font-size: 12px;
  line-height: 1.5;
  text-align: center;
  color: rgba(255,255,255,0.5);
}
/* .ida-fg-2's own 1rem bottom margin collapses through the form and lands between the
   submit and the note, so the gap measured 16px against the source's 8. The grid is
   always the last visible thing in these forms — only the hidden honeypot and the
   response output follow it — so it carries no trailing margin inside a CF7 form. */
.wpcf7-form .ida-fg-2 { margin-bottom: 0; }
.section-light .ida-form-note { color: rgba(16,24,32,0.50); }
.section-light .ida-form-note a { color: inherit; text-decoration: underline; }

/* Validation + response messages. */
.wpcf7-not-valid-tip { color: #FF8A8A; font-size: 13px; margin-top: 6px; }
.wpcf7-form .wpcf7-not-valid { border-color: #FF8A8A; }
.wpcf7-response-output {
  margin: 20px 0 0;
  padding: 14px 16px;
  border-radius: 10px;
  border: 1px solid var(--ida-line-strong);
  font-size: 15px;
}
.wpcf7-form.invalid .wpcf7-response-output,
.wpcf7-form.unaccepted .wpcf7-response-output { border-color: #FF8A8A; color: #FF8A8A; }
.wpcf7-form.sent .wpcf7-response-output { border-color: var(--ida-green); color: var(--ida-green-soft); }
.wpcf7-spinner { margin-left: 10px; }

/* Honeypot — every IDA form carries one. Must never be visible or focusable. */
.wpcf7-form .ida-honeypot,
.wpcf7-form .wpcf7-form-control-wrap[class*="honeypot"] {
  position: absolute !important;
  left: -9999px !important;
}

/* The cream-section form variant used to live here with `background: #fff` and a
   0.18 border — invented values, not the source's. It sat AFTER the correct block
   further up and silently won on source order, which is why the fields looked close
   but never right. Merged into the single block above, on the source's own numbers
   (0.03 fill, 0.12 border). Two rules for one thing is how that happens. */

/* ── Gravity Forms ──────────────────────────────────────────────────────
   Migration target for the CF7 block above (see inc/gf-migrate.php). Every value
   here is copied 1:1 from the .wpcf7-form rules — this section exists only because
   GF's DOM shape differs from CF7's, not because the design differs.

   Verified against GF 2.7.0.4's actual rendered output (gform-theme--no-framework
   mode) rather than assumed:
     - the field-level cssClass set in inc/gf-migrate.php (fl-field, ida-fieldset,
       ida-fg-full, ida-fg-half) lands on the .gfield wrapper, so .ida-fieldset,
       .ida-fg-full etc. above already apply — only the GF-native selectors below
       are new
     - <form class="ida-fg-2"> is the class target, NOT a grid container itself:
       the actual field list is .gform_fields, nested two levels inside the form
       (form > .gform_body > .gform_fields), and .gform_footer is a SIBLING of
       .gform_body, outside that nesting — so the grid goes on .gform_fields, and
       the footer just needs flex centring, no grid-column tricks
     - GF's built-in honeypot ("Enable Anti-spam Honeypot", turned on for every
       form in inc/gf-migrate.php) hides itself via its own CSS with
       `display:none !important` — confirmed by reading
       wp-content/plugins/gravityforms/assets/css/dist/basic.min.css directly,
       not assumed. Nothing to add here; unlike the off-screen-only trap this repo
       hit before, display:none removes it from the tab order and AT on its own.
     - GF shows a visible "(Required)" after every required label by default; CF7
       never did. Hidden below rather than left as a visual difference. */

.ida-gf-fg-2 .gform_fields {
  display: grid;
  gap: 0.75rem;
  margin-bottom: 1rem;
}
@media (min-width: 640px) { .ida-gf-fg-2 .gform_fields { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* !important: GF's own gravity-theme stylesheet sets .gform_wrapper.gravity-theme
   .gfield_required { display: inline-block } at higher specificity (3 classes vs
   2) — confirmed by walking document.styleSheets in a real browser, not assumed.
   This deliberately overrides that vendor default, which is what !important is
   actually for. */
.gform_wrapper .gfield_required_text,
.gform_wrapper .gfield_required { display: none !important; }

.gform_wrapper .gfield_label,
.gform_wrapper legend.gfield_label {
  display: block;
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 0.4rem;
}
.gform_wrapper .gfield.hidden_label > .gfield_label,
.gform_wrapper fieldset.hidden_label > legend.gfield_label {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border-width: 0;
}

.gform_wrapper .ginput_container { display: block; }
.gform_wrapper input[type="text"],
.gform_wrapper input[type="email"],
.gform_wrapper input[type="tel"],
.gform_wrapper input[type="url"],
.gform_wrapper select,
.gform_wrapper textarea {
  width: 100%;
  background: rgba(255,255,255,0.05);
  border: 1px solid var(--ida-line-strong);
  border-radius: 10px;
  padding: 14px 16px;
  color: #fff;
  font-size: 15px;
  font-family: inherit;
  transition: border-color 180ms ease, background 180ms ease;
}
.gform_wrapper textarea { min-height: 120px; resize: vertical; }
.gform_wrapper input::placeholder,
.gform_wrapper textarea::placeholder { color: var(--ida-text-dim); }
.gform_wrapper input:focus,
.gform_wrapper select:focus,
.gform_wrapper textarea:focus {
  outline: none;
  border-color: var(--hub-accent);
  background: rgba(255,255,255,0.08);
}
.gform_wrapper select option { background: var(--ida-navy-brand); color: #fff; }

/* Radio groups — GF nests choices in .gfield_radio > .gchoice, not CF7's flatter
   .wpcf7-list-item. Same flex-wrap row, same gaps as the CF7 block above. */
.gform_wrapper .gfield_radio {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.75rem;
}
.gform_wrapper .gchoice { margin: 0; }
.gform_wrapper .gchoice label {
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  font-size: 15px;
}
.gform_wrapper input[type="radio"],
.gform_wrapper input[type="checkbox"] { accent-color: var(--hub-accent); width: 18px; height: 18px; }

/* Submit — .gform_footer is a sibling of .gform_body, not a grid item, so this is
   plain flex centring rather than the CF7 block's grid-column: 1 / -1. */
.gform_wrapper .gform_footer { display: flex; justify-content: center; margin-top: 0.5rem; }
.hub-hero-form .gform_wrapper .gform_footer { justify-content: flex-start; }
.gform_wrapper .gform_button {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: var(--hub-accent);
  color: #fff;
  border: 0;
  border-radius: 999px;
  padding: 15px 30px;
  font-weight: 700;
  font-size: 15px;
  letter-spacing: -0.01em;
  cursor: pointer;
  transition: transform 180ms ease, filter 180ms ease;
}
.gform_wrapper .gform_button:hover { filter: brightness(1.08); transform: translateY(-1px); }
.gform_wrapper .gform_button:active { transform: translateY(0); }

/* Validation — GF marks the field wrapper .gfield_error and prints its own message
   div; CF7's colours and sizes carried over exactly. */
.gform_wrapper .gfield_error input,
.gform_wrapper .gfield_error select,
.gform_wrapper .gfield_error textarea { border-color: #FF8A8A; }
.gform_wrapper .gfield_validation_message,
.gform_wrapper .validation_message { color: #FF8A8A; font-size: 13px; margin-top: 6px; }
.gform_wrapper .gform_validation_errors {
  margin: 20px 0 0;
  padding: 14px 16px;
  border-radius: 10px;
  border: 1px solid #FF8A8A;
  color: #FF8A8A;
  font-size: 15px;
}

/* ── Forms on a LIGHT section — same values as the CF7 block's .section-light rules. */
.section-light .gform_wrapper input[type="text"],
.section-light .gform_wrapper input[type="email"],
.section-light .gform_wrapper input[type="tel"],
.section-light .gform_wrapper input[type="url"],
.section-light .gform_wrapper select,
.section-light .gform_wrapper textarea {
  background: rgba(16,24,32,0.03);
  border: 1px solid rgba(16,24,32,0.12);
  border-radius: 8px;
  padding: 12px 16px;
  color: #0F1116;
  font-size: 14px;
}
.section-light .gform_wrapper input::placeholder,
.section-light .gform_wrapper textarea::placeholder { color: rgba(16,24,32,0.45); }
.section-light .gform_wrapper input:focus,
.section-light .gform_wrapper select:focus,
.section-light .gform_wrapper textarea:focus {
  border-color: var(--hub-accent);
  background: rgba(16,24,32,0.05);
}
.section-light .gform_wrapper select option { background: #fff; color: #0F1116; }
.section-light .gform_wrapper .gfield_radio { font-size: 14px; color: rgba(16,24,32,0.85); }
.section-light .gform_wrapper .gchoice label { font-size: 14px; gap: 0.5rem; }

/* Hero form submit button full width on mobile — GF equivalent of the CF7
   body.page-id-34 rule further down; .gform_footer needs no <p>-unwrapping since
   GF doesn't run its output through wpautop. */
@media (max-width: 767px) {
  body.page-id-34 .hub-hero-form .gform_wrapper .gform_footer { justify-content: stretch; }
  body.page-id-34 .hub-hero-form .gform_wrapper .gform_button { width: 100%; display: block; }
}

/* Modal form rhythm — same as .modal-form .wpcf7-form select above. */
.modal-form .ida-gf-fg-2 .gform_fields { gap: 10px; }
.modal-form .gform_wrapper select { padding: 17px 14px; height: 56.5px; }

/* ── .hub-hero-form white card — GF equivalent of the .wpcf7-form rules at ~1435.
   Third styling context, distinct from both the dark base and .section-light:
   the /become-a-client/ hero form and (via shared markup) the Access Pricing
   modal both sit in a white card, not on a dark or near-white section background.
   Missing this was the actual gap the CF7 port never had, because CF7 shared one
   .wpcf7-form selector everywhere — GF's .gform_wrapper needs the same three-way
   split spelled out explicitly. */
.hub-hero-form .gform_wrapper{ margin: 0; }
.hub-hero-form .gform_wrapper input[type="text"],
.hub-hero-form .gform_wrapper input[type="email"],
.hub-hero-form .gform_wrapper input[type="tel"],
.hub-hero-form .gform_wrapper input[type="url"],
.hub-hero-form .gform_wrapper select,
.hub-hero-form .gform_wrapper textarea{
  background: #F4F1EA;
  border: 1px solid rgba(15, 17, 22, 0.12);
  color: #0F1116;
}
.hub-hero-form .gform_wrapper input::placeholder,
.hub-hero-form .gform_wrapper textarea::placeholder{ color: rgba(15, 17, 22, 0.45); }
.hub-hero-form .gform_wrapper input:focus,
.hub-hero-form .gform_wrapper select:focus,
.hub-hero-form .gform_wrapper textarea:focus{
  border-color: var(--ida-orange, #E27B27);
  outline: none;
  background: #ffffff;
}
.hub-hero-form .gform_wrapper select option{ background: #ffffff; color: #0F1116; }
.hub-hero-form .gform_wrapper .gfield_label{ color: #0F1116; }

/* In-field floating labels — same treatment as .hub-hero-form .fl-field above,
   retargeted at GF's .gfield wrapper (fl-field is added via cssClass in
   inc/gf-migrate.php on the same fields CF7's source template wrapped in
   <div class="fl-field">). No wpautop <p>/<br> stripping needed — GF doesn't
   run its output through wpautop, so there's nothing injected to hide. */
.hub-hero-form .gfield.fl-field{
  position: relative;
  display: flex; flex-direction: column;
}
.hub-hero-form .gfield.fl-field .gfield_label{
  position: absolute;
  left: 14px;
  top: 8px;
  pointer-events: none;
  color: rgba(15, 17, 22, 0.65);
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-weight: 500;
  margin: 0;
  background: transparent;
  line-height: 1;
  z-index: 1;
}
.hub-hero-form .gfield.fl-field input[type="text"],
.hub-hero-form .gfield.fl-field input[type="email"],
.hub-hero-form .gfield.fl-field input[type="tel"],
.hub-hero-form .gfield.fl-field textarea{
  padding: 22px 14px 10px 14px;
}
.hub-hero-form .gfield.fl-field input::placeholder,
.hub-hero-form .gfield.fl-field textarea::placeholder{
  color: rgba(15, 17, 22, 0.35);
  opacity: 1;
}

/* ── Reduced motion ─────────────────────────────────────────────────────
   The static build only opted .hl out of animation. Honour the preference
   across every entrance animation. */
@media (prefers-reduced-motion: reduce) {
  .reveal, .reveal-line > span, .hl {
    animation: none !important;
    transition: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  .hl { background-size: 100% 100% !important; }
  html { scroll-behavior: auto !important; }
}

/* ============================================================
   §4 HEADER + FOOTER LAYOUT
   ============================================================
   The static build expressed this layout as inline Tailwind utilities on the
   markup (max-w-[1400px] mx-auto px-6 lg:px-10, grid lg:grid-cols-12,
   lg:col-span-4 ...). Per the project rule that global.css drives all visual
   styles, the same values are named classes here. Only .header-bar height and
   the nav/megamenu/drawer internals came over from the static <style> block;
   everything below is the layout those utilities used to provide.
   ============================================================ */

/* ── Shared container ───────────────────────────────────────────────────── */
.ida-container {
  max-width: var(--container-max, 1400px);
  margin-inline: auto;
  padding-inline: 1.5rem;
}
@media (min-width: 1024px) {
  .ida-container { padding-inline: 2.5rem; }
}

/* ── Header ─────────────────────────────────────────────────────────────── */
.header-bar {
  position: fixed;
  inset-inline: 0;
  top: 0;
  z-index: 100;
  /* height: 72px comes from §2 */
}
.header-inner {
  max-width: var(--container-max, 1400px);
  margin-inline: auto;
  padding-inline: 1.5rem;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
}
@media (min-width: 1024px) {
  .header-inner { padding-inline: 2.5rem; }
}
.header-logo { display: flex; align-items: center; flex: 0 0 auto; }
.ida-logo { height: 52px; width: auto; display: block; }
.header-right { display: flex; align-items: center; gap: 0.75rem; flex: 0 0 auto; }

/* The logo lockup inverts to white on pages whose hero is a flat accent fill.
   The static build targeted img[alt*="International Dental Arts"], which broke
   whenever an editor changed the alt text. Keyed to the class instead.
   Home is excluded per client direction — the coloured logo reads better on
   the gradient hero than the pure-white silhouette. */
body.solid-hero:not(.home) .header-bar:not(.is-past-hero) .ida-logo { filter: brightness(0) invert(1); }

.nav-chev { flex: 0 0 auto; opacity: 0.6; transition: transform 200ms ease; }
.nav-mega-wrapper { position: relative; display: flex; align-items: center; }
.nav-mega-wrap[aria-expanded="true"] .nav-chevron,
.nav-mega-wrap.is-open .nav-chev { transform: rotate(180deg); }

.mega-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 2rem;
}

/* ── Mobile drawer rows ──────────────────────────────────────────────────────
   Nothing here. .mobile-link and .mobile-mega-item were invented names for elements
   the source leaves unclassed, and they had their own rules that COMPETED with the
   ported ones above: 1.25rem/1rem padding against the source's 18px/4px, and
   var(--ida-text-mute) against rgba(255,255,255,0.85). Whichever block loaded last
   won, by accident rather than intent. The markup emits neither class now, so
   `.mobile-drawer-nav > a` and `.mobile-mega-group > a:not(.mobile-mega-cat)` govern
   both — which is what the static build does. */

/* ── Footer ─────────────────────────────────────────────────────────────── */
.site-footer {
  position: relative;
  background: var(--ida-navy-deep);
}
.footer-inner {
  max-width: var(--container-max, 1400px);
  margin-inline: auto;
  padding: 5rem 1.5rem;
}
@media (min-width: 1024px) {
  .footer-inner { padding-inline: 2.5rem; }
}
.footer-grid {
  display: grid;
  gap: 2.5rem;
  margin-bottom: 4rem;
}
@media (min-width: 1024px) {
  .footer-grid { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .footer-brand      { grid-column: span 4; }
  .footer-grid > div:not(.footer-brand) { grid-column: span 2; }
}
.footer-tagline {
  margin-top: 1.5rem;
  font-size: 0.9375rem;
  line-height: 1.65;
  color: var(--ida-text-mute);
  max-width: 34ch;
}
.footer-social {
  display: flex;
  gap: 0.75rem;
  margin-top: 1.5rem;
  list-style: none;
  padding: 0;
}
.footer-social a {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 999px;
  border: 1px solid var(--ida-line-strong);
  color: var(--ida-text-mute);
  transition: color 200ms ease, border-color 200ms ease, background 200ms ease;
}
.footer-social a:hover {
  color: #fff;
  border-color: var(--ida-purple-bright);
  background: rgba(106, 110, 232, 0.12);
}
.footer-address {
  font-style: normal;
  font-size: 0.9375rem;
  line-height: 1.7;
  color: var(--ida-text-mute);
}
.footer-phone {
  display: inline-block;
  margin-top: 0.5rem;
  font-size: 0.9375rem;
  color: var(--ida-purple-bright);
}
.footer-phone:hover { color: #fff; }

.footer-links { list-style: none; padding: 0; display: grid; gap: 0.75rem; }
.footer-links a {
  font-size: 0.9375rem;
  color: var(--ida-text-mute);
  transition: color 180ms ease;
}
.footer-links a:hover { color: #fff; }

.footer-newsletter-blurb {
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--ida-text-mute);
  margin-bottom: 1rem;
}

.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-top: 2rem;
}
.footer-copyright { font-size: 0.8125rem; color: var(--ida-text-dim); }

/* The Hueston credit. inline-flex so the wordmark sits on the text baseline rather
   than dropping below it, and the SVG is given an explicit height because an SVG with
   no intrinsic size renders at whatever the box allows. */
.footer-credit {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  color: inherit;
  transition: opacity 0.2s ease;
}
.footer-credit:hover { opacity: 0.65; }
.footer-credit img { height: 1rem; width: auto; display: inline-block; vertical-align: middle; }
.footer-legal {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  list-style: none;
  padding: 0;
}
.footer-legal a { font-size: 0.8125rem; color: var(--ida-text-dim); }
.footer-legal a:hover { color: #fff; }

/* ── Testimonials carousel ──────────────────────────────────────────────
   Layout only. Type, colour and alignment come from utilities in the template,
   matching the source: display type 22→38px, left-aligned, 820px measure.
   An earlier version here centred everything at 23px and added CSS quote marks,
   which was wrong on all three counts. */
.testimonial-wrap {
  position: relative;
  display: flex;
  align-items: center;
  gap: 1rem;
}
.testimonial-track { position: relative; width: 100%; }
.testimonial-slide > p { margin: 0; }
@media (max-width: 900px) {
  .testimonial-arrow { display: none; }
}

/* ── Blog: cards, filters, pagination, article ──────────────────────────── */
.post-card {
  display: flex;
  flex-direction: column;
  border-radius: 16px;
  overflow: hidden;
  background: #fff;
  border: 1px solid rgba(16, 24, 32, 0.08);
  transition: transform 250ms ease, box-shadow 250ms ease;
}
.post-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md, 0 4px 12px rgba(0,0,0,.10)); }
.post-card-img { display: block; aspect-ratio: 16 / 10; overflow: hidden; }
.post-card-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.post-card-placeholder {
  display: block; width: 100%; height: 100%;
  background: linear-gradient(135deg, var(--ida-navy-brand), var(--ida-navy-deep));
}
.post-card-body { padding: 1.5rem; display: flex; flex-direction: column; gap: 0.6rem; flex: 1; }
/* !important: .section-light(-alt) .smcaps (two classes) otherwise outranks this
   single-class selector and wins with its default orange, regardless of source order. */
.post-card-cat  { color: var(--ida-specialty-blue) !important; }
/* When the category label is rendered as an <a> (clicks through to the
   category archive), keep it flush with the div variant — no underline at
   rest, subtle darken on hover so it reads as clickable. */
a.post-card-cat { text-decoration: none; transition: opacity .15s ease; }
a.post-card-cat:hover { opacity: 0.72; }
.post-card-date { font-size: 12px; color: rgba(16, 24, 32, 0.5); }
.post-card-excerpt { font-size: 14px; line-height: 1.6; color: rgba(16, 24, 32, 0.7); flex: 1; }

/* Real category links, replacing the static build's JS-only pills — those were
   display:none under 768px and invisible to crawlers. */
.post-filters { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.post-filter {
  padding: 0.5rem 1rem;
  border-radius: 999px;
  border: 1px solid rgba(16, 24, 32, 0.14);
  font-size: 14px;
  transition: border-color 180ms ease, background 180ms ease;
}
.post-filter:hover, .post-filter.is-active {
  border-color: var(--hub-accent);
  background: color-mix(in srgb, var(--hub-accent) 10%, transparent);
}

.post-pagination { margin-top: 3rem; }
.post-pagination .nav-links { display: flex; flex-wrap: wrap; gap: 0.5rem; justify-content: center; }
.post-pagination .page-numbers {
  padding: 0.5rem 0.9rem;
  border-radius: 8px;
  border: 1px solid rgba(16, 24, 32, 0.14);
  font-size: 14px;
}
.post-pagination .page-numbers.current {
  background: var(--hub-accent);
  border-color: var(--hub-accent);
  color: #fff;
}

/* Article header + share */
.article-title { font-size: clamp(36px, 4.5vw, 60px); line-height: 1.08; }
.article-byline {
  display: flex; flex-wrap: wrap; gap: 0.75rem;
  margin-top: 2rem; font-size: 14px; color: var(--ida-text-dim);
}
.article-byline > span + span::before { content: '· '; }
/* Featured image sibling of the article header. The header carries the corner
   pattern behind overflow:hidden (which clips it), so the image can't live
   inside — it would get clipped where it bleeds into the body section. Instead
   we render it as a sibling and pull it UP with a big negative margin-top so
   it visually sits over the header's bottom half (with the pattern behind),
   then push a smaller negative margin-bottom so its bottom edge crosses the
   header/body seam by ~100px. */
.article-featured {
  position: relative;
  z-index: 3;
  margin-top: -160px;
  margin-bottom: -100px;
}
.article-featured img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; display: block; border-radius: 14px; }
@media (max-width: 767px) {
  .article-featured { margin-top: -110px; margin-bottom: -60px; }
}
/* Body section padding — bumped when a featured image bleeds into the top
   so the copy still starts below the image. */
.article-body { padding: 90px 0; position: relative; z-index: 1; }
.article-body--with-featured { padding: 190px 0 90px; }
@media (max-width: 767px) {
  .article-body--with-featured { padding: 120px 0 70px; }
}
/* Lift the whole hero header above the body section so the featured image
   (which lives inside it) paints over the cream body bg where they overlap. */
article > header.has-featured { z-index: 2; }

.article-share {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1rem;
  margin-top: 3.5rem; padding-top: 1.75rem;
  border-top: 1px solid rgba(16, 24, 32, 0.12);
  max-width: 720px;
}
/* Author row, on the same rule as the share links. Ported from the source: a round
   accent chip with the initials, the team name in display type, and the strapline
   beneath. It sits left, the share links right, hence justify-content: space-between
   on .article-share. */
.article-author { display: flex; align-items: center; gap: 1rem; margin-right: auto; }
.article-author-chip {
  width: 48px; height: 48px; flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  border-radius: 999px;
  background: var(--hub-accent, var(--ida-orange)); color: #fff;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 700;
  font-size: 16px; letter-spacing: -0.01em;
}
.article-author-name {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 700;
  font-size: 16px; letter-spacing: -0.015em; color: #0F1116;
}
.article-author-strap { font-size: 13px; color: rgba(16, 24, 32, 0.55); margin-top: 2px; }

.article-share-links { display: flex; align-items: center; gap: 0.5rem; }
.article-share-links a,
.article-share-links button {
  display: inline-flex; align-items: center; gap: 0.5rem;
  height: 38px; padding: 0 0.85rem;
  border-radius: 999px;
  border: 1px solid rgba(16, 24, 32, 0.14);
  background: transparent;
  color: rgba(16, 24, 32, 0.65);
  font-size: 13px; font-weight: 600;
  cursor: pointer;
  transition: color 180ms ease, border-color 180ms ease, background 180ms ease;
}
.article-share-links a:hover,
.article-share-links button:hover {
  color: #fff; background: var(--hub-accent); border-color: var(--hub-accent);
}
.arrow-link--back::before { content: '\2190'; margin-right: 0.4rem; }

/* 404 code block */
.error-code {
  font-size: clamp(72px, 12vw, 160px);
  line-height: 1;
  color: var(--ida-orange);
  opacity: 0.9;
}

/* Scheduler embed (Thank You page, optional) */
.scheduler-embed { border-radius: 16px; overflow: hidden; background: #fff; }

/* ── Flexible-page layout components ────────────────────────────────────
   The static build styled these inline. Values transcribed from the service
   hub and Lab Forms / Digital Impressions pages. */


/* Non-linking service cards (the Nightguards hub) — hover suppressed. */
.service-card--static { cursor: default; }
.service-card--static:hover .service-card-img { transform: none; }
.service-card--static:hover { transform: none; box-shadow: none; }

/* Contact detail rows ────────────────────────────────────────────────────────
   Ported verbatim. The previous version was a 2-column label/value grid with a
   BOTTOM border and 16px body copy; the source is a stacked list with a TOP
   border, 1.5rem vertical padding, and the value set in display type at 19-22px
   with no underline. Every one of those differences was visible. */
.contact-rows { list-style: none; padding: 0; margin: 0; }
.contact-row {
  border-top: 1px solid rgba(16,24,32,0.10);
  padding: 1.5rem 0;
}
.contact-row .smcaps { display: block; margin-bottom: 0.5rem; }
.contact-row-value {
  font-family: var(--font-display);
  font-size: 22px;
  letter-spacing: -0.02em;
  line-height: 1.35;
  color: #0F1116;
}
/* Rows whose value is a sentence rather than a single address sit a step down,
   matching the source's 19-20px on those. */
.contact-row-value--prose { font-size: 19px; line-height: 1.4; }
/* The postal address: three lines of display type at 20px, between the single-line
   22px addresses and the 19px prose rows. It was rendering at 22px. */
.contact-row-value--mid { font-size: 20px; line-height: 1.35; }
.contact-row-value a { color: inherit; transition: opacity .2s ease; }
.contact-row-value a:hover { opacity: 0.7; }

/* Hero variant: dark background, so separators and value text flip light.
   Extra top margin gives the description/CTA breathing room before the first divider. */
.contact-rows--hero { margin-top: 3.5rem !important; padding-top: 4px; }
.contact-rows--hero .contact-row { border-top-color: rgba(255, 255, 255, 0.12); padding: 1.1rem 0; }
.contact-rows--hero .contact-row:last-child { border-bottom: 1px solid rgba(255, 255, 255, 0.12); }
.contact-rows--hero .contact-row-value { color: #fff; font-size: 18px; }
.contact-rows--hero .contact-row-value--mid { font-size: 17px; }
.contact-rows--hero .contact-row-value--prose { font-size: 16px; color: rgba(255,255,255,0.85); }

/* Tab panel shell: responsive inner padding. */
.tab-panel-shell { padding: 20px; }
@media (min-width: 640px) { .tab-panel-shell { padding: 30px; } }
@media (min-width: 1024px) { .tab-panel-shell { padding: 50px; } }

/* Tab panel: right-column stacked steps with color-coded accents + separators. */
.tab-steps { list-style: none; padding: 0; margin: 0; }
.tab-step { border-top: 1px solid rgba(16, 24, 32, 0.10); padding: 20px 4px; }
.tab-step:first-child { border-top: none; padding-top: 0; }
.tab-step:last-child { padding-bottom: 0; }
.tab-step-head {
  display: flex; align-items: baseline; gap: 14px;
  color: var(--step-accent, var(--ida-orange));
  margin-bottom: 6px;
}
.tab-step-num { display: none; }
.tab-step-label {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-weight: 600;
}
.tab-step-heading {
  font-family: var(--font-display);
  font-size: 20px;
  letter-spacing: -0.01em;
  line-height: 1.25;
  color: #101820;
  margin: 4px 0 6px;
}
.tab-step-body {
  font-size: 15px;
  line-height: 1.55;
  color: rgba(16, 24, 32, 0.7);
}
.tab-step-body p { margin: 0; }

/* Tab panel image */
.tab-img { aspect-ratio: 4 / 3; border-radius: 16px; overflow: hidden; }
.tab-img img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Form wrapper — constrains CF7 output to a readable measure. */
.ida-form { max-width: 720px; }

/* ── About + Schedule layout components ─────────────────────────────────── */
.story-scroller { display: grid; gap: 4rem; }
.story-slide {
    /* No left padding: .story-text-col already insets 56px, which is where the
       pagination above the slides sits, and a second 40px here pushed the copy
       out of alignment with it. The remaining padding is vestigial card styling
       from a version where the slide carried its own --story-bg; it renders
       transparent now, so there is no background edge for it to respect. */
    padding: 2.5rem 2.5rem 2.5rem 0;
    border-radius: 20px; background: var(--story-bg, transparent);
  }
.story-slide-img { aspect-ratio: 3 / 4; border-radius: 16px; overflow: hidden; }
.story-slide-img img { width: 100%; height: 100%; object-fit: cover; display: block; }



.note-photo { aspect-ratio: 3 / 4; border-radius: 16px; overflow: hidden; }
.note-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.note-signature { margin-top: 2rem; display: flex; flex-direction: column; gap: 0.15rem; }
.quote-card {
  display: flex; gap: 0.9rem;
  padding: 1.5rem;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--ida-line-strong);
}
.section-light .quote-card { background: #fff; border-color: rgba(16, 24, 32, 0.1); }
.quote-card p { font-size: 16px; line-height: 1.6; font-style: italic; }
.quote-card svg { flex: 0 0 auto; margin-top: 3px; }

/* ── Event info panel ───────────────────────────────────────────────────── */
.event-panel {
  display: grid;
  gap: 1.5rem;
  padding: 1.75rem;
  border-radius: 16px;
  background: #fff;
  border: 1px solid rgba(16, 24, 32, 0.1);
}
@media (min-width: 768px) {
  .event-panel { grid-template-columns: repeat(3, minmax(0, 1fr)); align-items: center; }
}
.event-panel-cell { display: flex; flex-direction: column; gap: 0.3rem; }
.event-panel-cell--cta { justify-content: center; }
.event-panel-value {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 700; letter-spacing: -0.02em;
  font-size: 18px; color: var(--ida-navy-brand);
}
.event-panel-sub { font-size: 14px; color: rgba(16, 24, 32, 0.6); }

/* ── CF7 field groups (used by _migrate/cf7-seed) ───────────────────────── */
/* gap-3 in the source, which is 0.75rem — this was 1rem. */
.ida-fg-2  { display: grid; gap: 0.75rem; margin-bottom: 1rem; }
@media (min-width: 640px) { .ida-fg-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.ida-fg-2 label {
  display: block;
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 0.4rem;
}

/* ── Form field spans and fieldsets ─────────────────────────────────────────
   .ida-fg-full is the source's sm:col-span-2: the message textarea, the practice
   address, and each radio fieldset run the full width of the two-column grid. */
.ida-fg-full { grid-column: 1 / -1; }

.ida-fieldset { border: 0; padding: 0; margin: 0; }
.ida-fieldset legend {
  display: block;
  font-size: 0.8125rem;
  color: var(--ida-text-mute);
  margin-bottom: 0.75rem;
  padding: 0;
}

/* The footer newsletter strip was removed on 7 Aug 2026 — the team replaced it with the
   consultation CTA (commit 558dab3), so .ida-newsletter-row had nothing emitting it. The
   CF7 "Newsletter" form still exists in wp-admin if it is ever wanted back; the styles are
   in git history at this commit. */


/* ── Share buttons ──────────────────────────────────────────────────────── */
.share-copy-link { font: inherit; }
.share-copy-label { letter-spacing: 0.01em; }

/* ── Footer newsletter column ───────────────────────────────────────────── */
.footer-newsletter { display: flex; flex-direction: column; }


/* ── Reveal safety net ──────────────────────────────────────────────────────
   no-js safety: the reveal system hides content until JS adds .in. If the
   script fails to load or throws, that leaves the page permanently blank —
   which is exactly what happened once already. <html> gets .ida-js from the
   script itself, so the hidden state only ever applies when JS is alive to
   undo it. */
html:not(.ida-js) .reveal,
html:not(.ida-js) .reveal-line > span {
  opacity: 1 !important;
  transform: none !important;
}


/* ── Service-detail decision aid ─────────────────────────────────────────────
   Ported from the detail pages' 3rd <style> block. The active state is driven
   by [aria-selected] on the button, not by a class — so the a11y attribute and
   the visual state can never disagree. */
.decision-tabs { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.decision-tab {
  text-align: left;
  width: 100%;
  background: transparent;
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 14px;
  padding: 1.1rem 1.4rem;
  color: rgba(255,255,255,0.85);
  font-family: var(--font-display);
  font-size: clamp(15px, 1.35vw, 17px);
  letter-spacing: -0.01em;
  line-height: 1.3;
  cursor: pointer;
  transition: background .2s ease, border-color .2s ease, color .2s ease, transform .2s ease;
  display: flex; align-items: center; gap: 0.85rem;
}
.decision-tab:hover { background: rgba(255,255,255,0.04); border-color: rgba(255,255,255,0.22); }
.decision-tab[aria-selected="true"] {
  background: var(--hub-accent);
  border-color: var(--hub-accent);
  color: #fff;
}
.decision-tab[aria-selected="true"] .decision-tab-num { background: rgba(255,255,255,0.22); }
.decision-tab-num {
  flex-shrink: 0;
  width: 26px; height: 26px;
  border-radius: 999px;
  background: rgba(255,255,255,0.08);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 600;
  transition: background .2s ease;
}
.decision-panel { display: none; }
.decision-panel.is-active { display: block; animation: idaFadeIn .3s ease; }
@keyframes idaFadeIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }

/* ── Service-detail FAQ accent scope ────────────────────────────────────────
   The detail pages' 4th <style> block. Recolours the shared FAQ chrome to the
   page's --hub-accent; without it every detail page's FAQ icons read purple. */
.subservice-page .faq-icon { border-color: var(--hub-accent); color: var(--hub-accent); }
.subservice-page .faq-item.open .faq-icon {
  background: color-mix(in srgb, var(--hub-accent) 15%, transparent);
  border-color: var(--hub-accent);
}
.subservice-page .pill.pill--accent {
  background: var(--hub-accent);
  box-shadow: 0 12px 40px -10px color-mix(in srgb, var(--hub-accent) 55%, transparent);
}
.subservice-page .pill.pill--accent:hover {
  background: var(--hub-accent);
  box-shadow: 0 18px 48px -10px color-mix(in srgb, var(--hub-accent) 75%, transparent);
}

/* ── Flat (non-animating) accent highlight ──────────────────────────────────
   The cream sections on the service-detail pages highlight a word with a solid
   accent block that is present on load rather than sweeping in. The source did
   this with a repeated inline style on 42 spans, at two different horizontal
   paddings (0.10em on section headings, 0.08em in the FAQ) with no reason for
   the difference — standardised here on 0.10em. */
.hl-flat {
  /* Colour and horizontal padding are both overridable, because the source varies
     them per section: 0.10em on the detail-page headings, 0.08em in their FAQ,
     and 0 with --ida-purple on the For Dentists feature band. A heading that
     needs a different pair sets --hl-flat-color / --hl-flat-pad inline rather
     than earning its own modifier class. */
  background: var(--hl-flat-color, var(--hub-accent));
  color: #fff;
  padding: 0.04em var(--hl-flat-pad, 0.10em);
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

/* ── Corner pattern, accent-tinted top-left ─────────────────────────────────
   The prep-guide band on the service-detail pages. Same geometry as
   .has-corner-pattern-tl but painted in --hub-accent at 7% rather than white at
   6%, because it sits on cream. The source did this with an absolutely
   positioned <div> carrying 350 characters of inline mask CSS. */
.has-corner-pattern-tl-accent { position: relative; }
.has-corner-pattern-tl-accent::after {
  content: '';
  position: absolute;
  top: 0; left: 0;
  width: 42%;
  aspect-ratio: 1264.9 / 1355.3;
  background-color: var(--hub-accent);
  -webkit-mask-image: url('../images/ida-brand-pattern-corner-top-left.svg');
          mask-image: url('../images/ida-brand-pattern-corner-top-left.svg');
  -webkit-mask-size: contain;
          mask-size: contain;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: top left;
          mask-position: top left;
  pointer-events: none;
  opacity: 0.07;
  z-index: 1;
}

/* ══ Named components used by the flexible / thank-you / event templates ══════
   These class names were in the markup with no rules behind them, which renders
   as unstyled text — no error, no warning. Found by bin/check-classes.py.

   Declarations are lifted from the equivalent verbatim-ported sections on the
   service-detail pages, so a flexible-page ADA grid and a service-detail ADA
   grid look identical instead of merely similar.

   Base values assume a navy section, since that is the theme default; the
   .section-light overrides follow each block. */

/* ── Image fill ─────────────────────────────────────────────────────────────
   Passed to ida_image() from a dozen call sites. Where the parent already
   styles its img (.hub-feature-img) this is redundant; where it doesn't
   (.related-card-img, post hero, .note-photo) the image was overflowing. */
.img-cover { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ── ADA / procedure-code cards ─────────────────────────────────────────── */
.ada-card {
  border-radius: 0.75rem;
  padding: 1.5rem;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.10);
}
.ada-code {
  font-family: var(--font-display);
  letter-spacing: -0.03em;
  color: var(--hub-accent);
  font-size: 32px;
  line-height: 1;
}
.ada-label {
  font-family: var(--font-display);
  font-size: 16px;
  letter-spacing: -0.02em;
  margin-top: 0.75rem;
  color: #fff;
}
.ada-note { font-size: 13px; line-height: 1.55; margin-top: 0.5rem; color: rgba(255,255,255,0.65); }
.section-light .ada-card,
.section-light-alt .ada-card { background: #fff; border-color: rgba(16,24,32,0.10); }
.section-light .ada-label,
.section-light-alt .ada-label { color: #0F1116; }
.section-light .ada-note,
.section-light-alt .ada-note { color: rgba(16,24,32,0.62); }

/* ── System / feature cards (implant systems, next steps, event cards) ──── */
.system-card {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  border-radius: 0.75rem;
  padding: 1.75rem;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.10);
  transition: transform .25s cubic-bezier(.16,1,.3,1), border-color .25s ease;
}
a.system-card:hover { transform: translateY(-3px); border-color: var(--hub-accent); }
.system-note { font-size: 13.5px; line-height: 1.55; margin-top: 0.5rem; color: rgba(255,255,255,0.65); }
.section-light .system-card,
.section-light-alt .system-card { background: #fff; border-color: rgba(16,24,32,0.10); }
.section-light .system-note,
.section-light-alt .system-note { color: rgba(16,24,32,0.62); }

/* ── Related-content cards ──────────────────────────────────────────────── */
.related-card {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: 1rem;
  background: #FFFFFF;
  transition: transform .25s cubic-bezier(.16,1,.3,1);
}
.related-card:hover { transform: translateY(-4px); }
.related-card-img { aspect-ratio: 16 / 10; overflow: hidden; }
.related-card-body { display: flex; flex-direction: column; flex: 1; padding: 1.75rem; }
.related-card-body h3 { color: #0F1116; margin-bottom: 0.75rem; }
.related-card-body .smcaps { margin-bottom: 0.75rem; }
.related-card-text {
  font-size: 14px;
  line-height: 1.6;
  margin-bottom: 1.5rem;
  flex: 1;
  color: rgba(16,24,32,0.68);
}
.related-card .arrow-link { align-self: flex-start; color: var(--hub-accent); }

/* ── Stat pairs (flexible-page stat rows) ───────────────────────────────────
   The homepage uses .ring-stat, a circle. This is the plain stacked variant. */
.stat-value {
  font-family: var(--font-display);
  font-size: clamp(40px, 5vw, 64px);
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--hub-accent);
  font-variant-numeric: tabular-nums;
}
.stat-label { margin-top: 0.75rem; color: rgba(255,255,255,0.65); }
.section-light .stat-label,
.section-light-alt .stat-label { color: rgba(16,24,32,0.62); }

/* ── Cross-links inside the two-paths comparison bullets ────────────────────
   A few of those bullets are links to a sibling service page. The source styled
   each with an inline colour, which is not reproducible from inside a stored
   field, so the colour lives here and .compare-card is the hook. Underlined in
   both variants, matching the source. */
.compare-card a {
  color: var(--hub-accent);
  text-decoration: underline;
}
.compare-card--accent a {
  color: rgba(255,255,255,0.85);
}
.compare-card a:hover { text-decoration-thickness: 2px; }

/* ── Scanner-submission callout ─────────────────────────────────────────────
   The tinted link beside the download card on /lab-forms/. Ported from that
   page's own <style> block; its comment says it mirrors the homepage slider's
   .service-card-plus, adapted for a cream background. */
.scanner-callout-arrow {
  width: 44px; height: 44px;
  border-radius: 999px;
  background: #fff;
  border: 1px solid rgba(16,24,32,0.12);
  color: #0F1116;
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  transition: background .25s ease, border-color .25s ease, color .25s ease, transform .25s ease;
}
.scanner-callout:hover .scanner-callout-arrow,
.scanner-callout:focus-visible .scanner-callout-arrow {
  background: var(--ida-purple-bright);
  border-color: var(--ida-purple-bright);
  color: #fff;
  transform: scale(1.06);
}

/* ══ Story scrolling showcase ═════════════════════════════════════════════════
   /about/'s founding-story section. Ported from that page's own <style> block —
   the original CSS pass missed it entirely, so .story-sticky, .story-grid,
   .story-pagination and .story-pag-bar had no rules at all.

   The outer wrapper is deliberately N*100vh tall: that height is what drives the
   scroll-pinning, and the sticky inner panel maps scroll progress to a slide.
   The per-slide background colour and the light/dark text switch are set by JS
   as inline style + a data-fg attribute, because they change with the active
   slide rather than being fixed per section. */
.story-scroller { position: relative; min-height: 400vh; transition: background-color .8s ease; }

/* Dark text on a light slide background — green, in the source's palette. */
.story-scroller[data-fg="dark"] .story-slide .smcaps { color: rgba(15,17,22,0.55); }
.story-scroller[data-fg="dark"] .story-slide h2 { color: #0F1116; }
.story-scroller[data-fg="dark"] .story-slide p { color: rgba(15,17,22,0.78); }
.story-scroller[data-fg="dark"] .story-pag-bar { background: rgba(15,17,22,0.20); }
.story-scroller[data-fg="dark"] .story-pag-bar.is-active { background: rgba(15,17,22,0.85); }
.story-scroller[data-fg="dark"] .story-pag-bar:hover { background: rgba(15,17,22,0.50); }
.story-scroller[data-fg="dark"] .story-image-frame { border-color: rgba(0,0,0,0.10); }

.story-sticky {
  position: sticky; top: 0;
  height: 100vh; width: 100%;
  display: flex; align-items: stretch;
  overflow: hidden;
}
/* Bottom-right brand pattern on the sticky panel, under the image column. The
   SVG is natively dense at bottom-right, so unlike the top-left variant this one
   needs no rotation. */
.story-sticky::after {
  content: '';
  position: absolute; bottom: 0; right: 0;
  width: 42%;
  aspect-ratio: 1264.9 / 1355.3;
  background-color: #fff;
  -webkit-mask-image: url('../images/ida-brand-pattern-corner.svg');
          mask-image: url('../images/ida-brand-pattern-corner.svg');
  -webkit-mask-size: contain;      mask-size: contain;
  -webkit-mask-repeat: no-repeat;  mask-repeat: no-repeat;
  -webkit-mask-position: bottom right; mask-position: bottom right;
  pointer-events: none;
  opacity: 0.10;
  z-index: 0;
}

.story-grid {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  width: 100%; max-width: 1400px; margin: 0 auto;
}
.story-text-col {
  position: relative;
  padding: 64px 56px;
  display: flex; flex-direction: column; justify-content: center;
}
.story-pagination { display: flex; gap: 8px; margin-bottom: 30px; }
.story-pag-bar {
  height: 4px; width: 24px;
  border-radius: 2px;
  background: rgba(255,255,255,0.30);
  transition: width .5s ease, background-color .5s ease;
  cursor: pointer; border: 0; padding: 0;
}
.story-pag-bar.is-active { width: 48px; background: rgba(255,255,255,0.95); }
.story-pag-bar:hover { background: rgba(255,255,255,0.55); }

.story-slide-stack { position: relative; min-height: 320px; }
.story-slide {
  position: absolute; inset: 0;
  opacity: 0; transform: translateY(20px);
  transition: opacity .7s ease, transform .7s ease;
  pointer-events: none;
}
.story-slide.is-active { opacity: 1; transform: translateY(0); pointer-events: auto; }
.story-slide .smcaps { color: rgba(255,255,255,0.75); margin-bottom: 18px; }
.story-slide h2 { color: #fff; margin: 0 0 22px; text-wrap: balance; }
.story-slide p { color: rgba(255,255,255,0.85); max-width: 480px; margin: 0; }

.story-image-col {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  padding: 32px;
  z-index: 1;
}
.story-image-frame {
  position: relative;
  width: 82%; height: 75vh; max-height: 720px;
  border-radius: 16px; overflow: hidden;
  box-shadow: 0 24px 70px -10px rgba(0,0,0,0.35);
  border: 4px solid rgba(255,255,255,0.08);
}
.story-image-track { position: absolute; inset: 0; transition: transform .7s cubic-bezier(.65,0,.35,1); }
.story-image-slide { width: 100%; height: 100%; }
.story-image-slide img { width: 100%; height: 100%; object-fit: cover; display: block; }

@media (max-width: 767px) {
  /* minmax(0, 1fr), not 1fr. `1fr` is minmax(auto, 1fr), and that auto minimum
     let the single column grow to its content's max-content — the image
     filmstrip is four slides wide, so the column resolved to 1851px inside a
     375px grid and .story-sticky's overflow:hidden silently clipped every
     heading and paragraph mid-word. Capping the minimum at 0 makes the track
     take the space available instead. */
  .story-grid { grid-template-columns: minmax(0, 1fr); }

  /* Phones pin like desktop: panel held still, copy and image and background
     changing as you scroll. That needs .story-sticky to have a definite height,
     and its overflow:hidden clips whatever does not fit — so the panel has to
     be compact enough to fit the viewport. At the desktop type the tallest
     slide alone was 552px and image plus copy came to ~1000px against an 812px
     viewport, which is why an earlier attempt used height:auto and stopped
     pinning altogether. Everything below exists to make it fit.

     100svh, not 100vh: on a phone 100vh is the viewport with the address bar
     HIDDEN, so a panel sized to it is taller than what you can see and the copy
     ends up behind the browser chrome. svh is the small viewport, so it fits
     whether the bar is showing or not, and it does not resize as the bar hides. */
  /* Even spacing down the panel: image bottom to pagination, and pagination to
     eyebrow, are both this value. The first is the column's padding-top, the
     second the pagination's margin-bottom plus the slide's own padding-top —
     which is why the slide padding is zeroed below. There is ~110px of slack
     under the copy, so 24px is affordable. */
  .story-text-col { padding: 24px 24px 14px; }
  .story-pagination { margin-bottom: 24px; }
  /* The desktop rule is `40px 40px 40px 0` — a hanging indent for the pinned
     two-column panel. On mobile the top 40px pushed the eyebrow away from the
     pagination (a 48px gap against 10px above it) and the right 40px stopped the
     copy 36px short of the image's edge. Full width, flush top. */
  .story-slide { padding: 0; }
  .story-slide .smcaps { margin-bottom: 8px; }
  .story-slide h2 { font-size: 23px; margin: 0 0 10px; }
  .story-slide p { font-size: 14px; line-height: 1.5; }

  /* Image above the copy, edge to edge. Landscape rather than the desktop
     square: 1/1 ate 327px of an 812px viewport and left the copy no room. */
  .story-image-col {
    order: -1;
    /* Full width and square, as asked. That is 327px tall on a 375px phone, and
       the panel is only the viewport minus the header — so the copy below is set
       tighter than desktop to pay for it. See the type rules above. */
    width: calc(100% - 48px);
    height: auto;
    /* Full width on a phone, but capped so it cannot eat the panel. The square's
       height follows the viewport WIDTH while the panel follows its HEIGHT, so a
       wide-but-short viewport (a 700px phone in portrait wants a 652px square)
       would overflow. Capping the WIDTH keeps it square as it shrinks — capping
       the height would clamp one side and leave a rectangle. At every real phone
       size the cap is larger than the column, so it stays full width. */
    max-width: calc((100svh - var(--story-offset, 72px)) * 0.48);
    aspect-ratio: 1 / 1;
    margin: 20px auto 0;
    padding: 0;
    min-height: 0;
  }
  /* Border kept on mobile. box-sizing is border-box, so the FRAME spans 24-351
     in line with the pagination and the copy, and the photo content sits 4px
     inside that — which is the framed look, not a misalignment. */
  .story-image-frame { width: 100% !important; height: 100%; max-height: none; }
  .story-sticky::after { width: 75% !important; }
}

/* Pin only where the panel actually fits. Worst case is image (204) + its
   margin (14) + column padding (32) + pagination (16) + the tallest slide's
   copy (~390) ≈ 656px, so 700px of viewport leaves real headroom. Below that
   the block further down takes over with a stacked layout — an iPhone SE at
   667px reads it stacked rather than clipped.

   100svh, not 100vh: on a phone 100vh is the viewport with the address bar
   HIDDEN, so a panel sized to it is taller than the visible area and the copy
   ends up behind the browser chrome. svh is the small viewport, so it fits in
   either state and does not resize as the bar hides. */
@media (max-width: 767px) and (min-height: 800px) {
  /* One source of truth on the section; .story-sticky and .story-image-col both
     inherit it. Logged-in editors also lose the 46px admin bar, so the preview
     matches what visitors get instead of being 46px out. */
  .story-scroller { --story-offset: 72px; }
  body.admin-bar .story-scroller { --story-offset: 118px; }
  /* Pin BELOW the fixed header, not behind it. .header-bar is position:fixed at
     72px tall, so a panel pinned at top:0 put its image under the header — more
     than half of a 204px image was covered. Offsetting the sticky top by the
     header height costs that much panel height, hence the shorter image above
     and the higher min-height gate on this block. */
  .story-sticky {
    top: var(--story-offset);
    height: calc(100svh - var(--story-offset));
    min-height: 0;
  }

  /* Explicit rows. Both rows were auto, and a grid with a definite height
     distributes the leftover space EQUALLY between auto rows — so the image row
     took half the slack it had no use for and the copy row was left 273px of an
     812px panel, still clipping the tallest slide. Image sized to content, copy
     takes the rest. minmax(0, ...) on the copy row for the same reason the
     columns need it: a bare 1fr keeps an auto minimum and can outgrow the panel.
     The image is order:-1, and order drives grid auto-placement, so it is row 1
     despite coming second in the markup. */
  .story-grid { grid-template-rows: auto minmax(0, 1fr); }
  /* The slides are absolutely positioned, so they contribute no height and the
     stack collapses without this — the copy then overflowed the panel and
     .story-sticky's overflow:hidden clipped it. flex:1 makes the stack take
     whatever the image and padding leave, and inset:0 fills the slides into it. */
  .story-slide-stack { flex: 1 1 auto; min-height: 0; }
}

/* Too short to pin. The panel is the viewport minus the 72px header, and below
   800px of viewport that cannot hold a square image plus the copy without
   .story-sticky's overflow:hidden cutting the bottom off. An iPhone SE (667) and
   an 8 Plus (736) read it stacked; a landscape phone at ~375px is nowhere close. Falls back to the stacked
   reading layout, the same shape reduced motion gets. Must come AFTER the block
   above: same specificity, so source order decides.
   initStoryScroller bails here too — nothing should drive the background or the
   image track while every chapter is on screen at once. */
@media (max-width: 767px) and (max-height: 799px) {
  .story-scroller { min-height: 0 !important; }
  .story-sticky { position: static; height: auto; min-height: 0; }
  .story-slide-stack { min-height: 0; }
  .story-slide { position: static; opacity: 1; transform: none; pointer-events: auto; }
  .story-slide + .story-slide { margin-top: 2.25rem; }
  .story-pagination { display: none; }
  .story-image-track { position: static; transform: none !important; }
  .story-image-slide + .story-image-slide { display: none; }
}

/* No scroll-pinning when motion is reduced: the whole effect is scroll-driven, so
   the honest fallback is a plain stack of readable panels. */
@media (prefers-reduced-motion: reduce) {
  .story-scroller { min-height: 0 !important; }
  .story-sticky { position: static; height: auto; }
  .story-slide-stack { min-height: 0; }
  .story-slide { position: static; opacity: 1; transform: none; pointer-events: auto; margin-bottom: 3rem; }
  .story-image-track { position: static; transform: none !important; }
  .story-image-slide + .story-image-slide { margin-top: 1rem; }
  .story-pagination { display: none; }
}

/* ══ Modal (native <dialog>) ══════════════════════════════════════════════
   Used by the Access Pricing button on /become-a-client/. The card body is
   .hub-hero-form so the CF7 inputs inherit the top-of-page form treatment
   without a second style scope. */
.modal {
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  max-width: none;
  max-height: none;
}
.modal[open] {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100dvh;
  margin: 0;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: 24px 16px;
  z-index: 100;
}
.modal::backdrop {
  background: rgba(15, 17, 22, 0.55);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}
.modal-card {
  position: relative;
  max-width: 640px;
  margin: 40px auto;
}
.modal-card .hub-hero-form {
  margin-top: 0;
  padding: 32px 24px;
}
@media (min-width: 640px) {
  .modal-card .hub-hero-form { padding: 40px; }
}
.modal-title {
  font-size: clamp(24px, 3vw, 32px);
  line-height: 1.15;
  letter-spacing: -0.03em;
  color: #0F1116;
  margin: 0 0 6px;
}
.modal-sub {
  color: rgba(15, 17, 22, 0.65);
  font-size: 15px;
  line-height: 1.5;
  margin: 0 0 20px;
}
.modal-close {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 3;
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: #ffffff;
  border: 1px solid rgba(15, 17, 22, 0.12);
  border-radius: 999px;
  color: #0F1116;
  cursor: pointer;
  transition: background 0.2s, border-color 0.2s, transform 0.2s;
}
.modal-close:hover {
  background: rgba(15, 17, 22, 0.05);
  border-color: rgba(15, 17, 22, 0.28);
}
.modal-close:focus-visible {
  outline: 2px solid var(--ida-orange, #E27B27);
  outline-offset: 2px;
}
.modal-close svg { width: 14px; height: 14px; }

html.is-modal-open,
html.is-modal-open body { overflow: hidden; }

/* ══ Home merger banner ═══════════════════════════════════════════════════
   Fixed purple strip above the site header on the home page, replacing the
   popup that used to open over the hero on every load.

   .header-bar is position:fixed at top:0 and the hero sits underneath it, so
   the banner cannot just precede it in the flow. --merger-banner-h lives on the
   body class and offsets three things: the page content (padding-top), the
   header (top) and, when the admin bar is present, both again. Same mechanism
   as the /become-a-client/ sub-nav, which offsets downward instead of up.

   z-index 101 puts it over .header-bar's 100 so the two never overlap during
   the header's blur/solid transitions. */
body.has-merger-banner {
  --merger-banner-h: 44px;
  padding-top: var(--merger-banner-h);
}
.merger-banner {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 101;
  height: var(--merger-banner-h, 44px);
  background: var(--ida-purple, #3B3FB6);
  color: #ffffff;
  display: flex;
  align-items: center;
}
body.has-merger-banner .header-bar { top: var(--merger-banner-h); }
/* The admin bar pushes everything down; keep the banner under it, not behind. */
body.admin-bar.has-merger-banner .merger-banner { top: 32px; }
body.admin-bar.has-merger-banner .header-bar { top: calc(32px + var(--merger-banner-h)); }
@media screen and (max-width: 782px) {
  body.admin-bar.has-merger-banner .merger-banner { top: 46px; }
  body.admin-bar.has-merger-banner .header-bar { top: calc(46px + var(--merger-banner-h)); }
}
.merger-banner-inner {
  max-width: 1400px;
  width: 100%;
  margin-inline: auto;
  padding-inline: 1.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  font-size: 13px;
  line-height: 1;
}
@media (min-width: 1024px) {
  .merger-banner-inner { padding-inline: 2.5rem; }
}
.merger-banner-icon { display: inline-flex; flex-shrink: 0; }
/* 15px, against the popup's 22px: this reads as a marker beside one line of
   text rather than the illustration it was at the top of a modal card. */
.merger-banner-icon svg { width: 15px; height: 15px; }
.merger-banner-heading { font-weight: 600; letter-spacing: -0.01em; white-space: nowrap; }
.merger-banner-copy { color: rgba(255, 255, 255, 0.78); white-space: nowrap; }
.merger-banner-cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  background: rgba(255, 255, 255, 0.14);
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 999px;
  padding: 5px 12px;
  color: #ffffff;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  transition: background-color .2s ease, border-color .2s ease;
}
.merger-banner-cta:hover,
.merger-banner-cta:focus-visible {
  background: rgba(255, 255, 255, 0.24);
  border-color: rgba(255, 255, 255, 0.45);
}
/* Four inline items do not fit a phone. The question goes first, then the icon;
   the announcement and the CTA are the two that have to survive. */
@media (max-width: 900px) {
  .merger-banner-copy { display: none; }
}
@media (max-width: 620px) {
  body.has-merger-banner { --merger-banner-h: 40px; }
  .merger-banner-icon { display: none; }
  .merger-banner-inner { gap: 10px; padding-inline: 1rem; font-size: 12px; }
  .merger-banner-heading { font-size: 12px; }
  .merger-banner-cta { font-size: 11px; padding: 4px 10px; }
}

/* ══ Become a Client sub-nav ═══════════════════════════════════════════════
   Fixed pill bar directly under the site header on /become-a-client/. Each
   pill jumps to its section anchor via smooth scroll; active state syncs to
   the current in-view section. See template-parts/subnav-become-client.php
   and assets/js/global.js:initBecomeClientSubnav. */
body.page-id-34 { padding-top: 76px; }
.bc-subnav {
  position: fixed;
  top: 72px;
  left: 0;
  right: 0;
  z-index: 40;
  background: transparent;
  border-bottom: 0;
  box-shadow: none;
  pointer-events: none;
}
.bc-subnav-inner,
.bc-subnav-btn { pointer-events: auto; }
.bc-subnav-inner {
  max-width: 1400px;
  margin: 0 auto;
  padding: 10px 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.bc-subnav-inner::-webkit-scrollbar { display: none; }
@media (min-width: 1024px) {
  .bc-subnav-inner { padding: 10px 40px; gap: 14px; }
}
.bc-subnav-btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;
  padding: 10px 18px;
  border-radius: 999px;
  background: #ffffff;
  border: 1px solid rgba(15, 17, 22, 0.10);
  color: #0F1116;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease, transform 0.18s ease;
}
.bc-subnav-btn:hover {
  background: #F7F4EC;
  border-color: rgba(15, 17, 22, 0.22);
  transform: translateY(-1px);
  box-shadow: 0 8px 24px -14px rgba(0, 0, 0, 0.35);
}
.bc-subnav-btn.is-active {
  border-color: rgba(15, 17, 22, 0.28);
  box-shadow: 0 8px 24px -14px rgba(0, 0, 0, 0.35);
}
.bc-subnav-btn:focus-visible {
  outline: 2px solid var(--ida-orange, #E27B27);
  outline-offset: 2px;
}
.bc-subnav-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 999px;
  background: currentColor;
}
.bc-subnav-icon svg {
  width: 15px;
  height: 15px;
  color: #ffffff;
  stroke: #ffffff;
}
.bc-subnav-label { color: inherit; }

/* Anchor offset: when smooth-scroll lands on a section, its top must clear
   both the site header (72px) and the sub-nav (~69px). scroll-margin gives
   a per-target offset without messing with margins. Applied broadly so any
   element that happens to carry an id (dialog, misc div) gets the same
   clearance as the section rows. */
body.page-id-34 [id] {
  scroll-margin-top: 148px;
}
@media (max-width: 767px) {
  /* 10px gap between the site header (64px on mobile) and the sub-nav. */
  body.page-id-34 { padding-top: 72px; }
  .bc-subnav { top: 74px; }
  /* Row starts at the first pill instead of being centered — otherwise the
     overflow spills both sides on narrow screens and the user has to scroll
     right just to see BECOME A CLIENT. */
  .bc-subnav-inner {
    padding: 8px 12px;
    justify-content: flex-start;
    scroll-padding-inline: 12px;
  }
  .bc-subnav-btn { padding: 8px 12px; font-size: 11.5px; letter-spacing: 0.06em; }
  .bc-subnav-icon { width: 22px; height: 22px; }
  .bc-subnav-icon svg { width: 12px; height: 12px; }
}

/* Hero on tablet / mobile — form sits between the intro copy and the contact
   rows so the user hits the form before scrolling past the metadata. Uses
   `display: contents` on .hub-hero-content so its children (h1, p, contact-rows)
   can be individually ordered against the sibling form. */
@media (max-width: 1023px) {
  body.page-id-34 .hub-hero-grid {
    display: flex;
    flex-direction: column;
  }
  body.page-id-34 .hub-hero--with-form .hub-hero-content { display: contents; }
  body.page-id-34 .hub-hero--with-form .hub-hero-content > h1,
  body.page-id-34 .hub-hero--with-form .hub-hero-content > .text-h1 { order: 1; }
  body.page-id-34 .hub-hero--with-form .hub-hero-content > p { order: 2; }
  body.page-id-34 .hub-hero--with-form .hub-hero-form { order: 3; margin-top: 32px; }
  body.page-id-34 .hub-hero--with-form .hub-hero-content > .contact-rows { order: 4; }
}

/* Hero form submit button full width on mobile. The submit control lives
   inside a <p> that WordPress auto-wraps around CF7 output; that <p> only
   sizes to its content, so widening the button alone gives a narrow pill.
   Stretch the flex row, the wrapping <p>, and the input in turn. */
@media (max-width: 767px) {
  body.page-id-34 .hub-hero-form .wpcf7-form .wpcf7-submit-row { justify-content: stretch; }
  body.page-id-34 .hub-hero-form .wpcf7-form .wpcf7-submit-row > p {
    width: 100%;
    margin: 0;
  }
  body.page-id-34 .hub-hero-form .wpcf7-form input[type="submit"],
  body.page-id-34 .hub-hero-form .wpcf7-form .wpcf7-submit {
    width: 100%;
    display: block;
  }
}

/* ══ Lead Time Estimator ═══════════════════════════════════════════════════
   Interactive tool on /become-a-client/. Product picker + start-date picker
   → estimated ready date using business-day math (assets/js/global.js:
   initLeadTimeTool). Reads its product list from a data-attribute rendered
   by template-parts/sections/lead-time-tool.php. Colors reference the IDA
   green brand token so the tool matches its host section. */
:root {
  --ltt-accent: #35D52F;
  --ltt-accent-tint: rgba(53, 213, 47, 0.10);
  --ltt-accent-border: rgba(53, 213, 47, 0.30);
  --ltt-accent-focus: rgba(53, 213, 47, 0.18);
}
.ltt {
  margin: 40px auto 0;
  max-width: 860px;
}
/* Product reference menu — name on the left, N Days on the right, dashed
   separator, mirrors the ODL-style menu Sebastian referenced. */
.ltt-menu {
  list-style: none;
  padding: 0;
  margin: 0 0 24px;
}
.ltt-menu-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 0;
  border-bottom: 1px dashed rgba(15, 17, 22, 0.18);
  font-size: 15.5px;
  color: #0F1116;
}
.ltt-menu-row:first-child { padding-top: 4px; }
.ltt-menu-name {
  flex: 1 1 auto;
  min-width: 0;
  font-weight: 500;
}
.ltt-menu-days {
  flex: 0 0 auto;
  color: rgba(15, 17, 22, 0.7);
  font-variant-numeric: tabular-nums;
}
.ltt-card {
  background: #ffffff;
  border: 1px solid rgba(15, 17, 22, 0.08);
  border-radius: 20px;
  padding: 32px;
  box-shadow: 0 20px 60px -30px rgba(0, 0, 0, 0.35);
}
@media (min-width: 640px) {
  .ltt-card { padding: 40px; }
}
.ltt-controls {
  display: grid;
  gap: 16px;
  grid-template-columns: 1fr;
}
@media (min-width: 640px) {
  .ltt-controls { grid-template-columns: 1fr 1fr; gap: 20px; }
}
.ltt-field { display: flex; flex-direction: column; gap: 6px; }
.ltt-label {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--ltt-accent);
}
.ltt-select,
.ltt-input {
  appearance: none;
  -webkit-appearance: none;
  width: 100%;
  height: 52px;
  padding: 0 16px;
  font-size: 15px;
  color: #0F1116;
  background: #F4F1EA;
  border: 1px solid rgba(15, 17, 22, 0.12);
  border-radius: 12px;
  transition: border-color 0.15s, background 0.15s, box-shadow 0.15s;
}
.ltt-select {
  padding-right: 40px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'><path d='M1 1l5 5 5-5' stroke='%230F1116' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 16px center;
  background-size: 12px 8px;
}
.ltt-select:focus,
.ltt-input:focus {
  outline: none;
  background: #ffffff;
  border-color: var(--ltt-accent);
  box-shadow: 0 0 0 3px var(--ltt-accent-focus);
}
.ltt-variants {
  margin-top: 16px;
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.ltt-variants[hidden] { display: none; }
.ltt-variants .ltt-label { margin: 0; }
.ltt-toggle {
  display: inline-flex;
  background: #F4F1EA;
  border: 1px solid rgba(15, 17, 22, 0.12);
  border-radius: 999px;
  padding: 4px;
}
.ltt-toggle-btn {
  appearance: none;
  border: 0;
  background: transparent;
  padding: 8px 16px;
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: rgba(15, 17, 22, 0.7);
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.ltt-toggle-btn.is-active {
  background: #0F1116;
  color: #ffffff;
}
.ltt-toggle-btn:focus-visible {
  outline: 2px solid var(--ltt-accent);
  outline-offset: 2px;
}
.ltt-result {
  margin-top: 24px;
  padding: 24px;
  border-radius: 14px;
  background: var(--ltt-accent-tint);
  border: 1px solid var(--ltt-accent-border);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.ltt-result.is-empty {
  background: rgba(15, 17, 22, 0.03);
  border-color: rgba(15, 17, 22, 0.08);
}
.ltt-result-eyebrow {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--ltt-accent);
}
.ltt-result.is-empty .ltt-result-eyebrow { color: rgba(15, 17, 22, 0.5); }
.ltt-result-date {
  font-size: clamp(22px, 2.6vw, 28px);
  line-height: 1.15;
  letter-spacing: -0.025em;
  color: #0F1116;
}
.ltt-result-days {
  font-size: 14px;
  color: rgba(15, 17, 22, 0.65);
}
.ltt-result-days:empty { display: none; }
.ltt-result-shipping-note {
  font-size: 12.5px;
  color: rgba(15, 17, 22, 0.55);
  font-style: italic;
  margin-top: 2px;
}
.ltt-result.is-empty .ltt-result-shipping-note { display: none; }
.ltt-note {
  margin: 14px 0 0;
  font-size: 13px;
  color: rgba(15, 17, 22, 0.55);
  line-height: 1.5;
}
/* Intro paragraph on the lead-time section reads at pure white per client
   direction. The shared header partial sets a dark inline color on light
   backgrounds and treats `accent` as light, so an inline style overrides
   any class-based rule — !important is scoped to the LTT section only. */
section.section-accent:has(.ltt) .ida-container > div:first-child p { color: #ffffff !important; }
/* Dark sections invert the tool's card so it still reads. */
[style*="ida-navy"] .ltt-card,
[style*="ida-black"] .ltt-card,
.section-accent .ltt-card {
  color: #0F1116;
}

/* Consistent rhythm across the modal form — the base `.hub-hero-form` mixes
   floating-label text fields (56px tall) with plain selects (49px tall), which
   reads as two visually separate row groups. In the modal scope only, make
   selects match the text-input height so all six rows share one rhythm. */
.modal-form .ida-fg-2 { gap: 10px; }
.modal-form .wpcf7-form select { padding: 17px 14px; height: 56.5px; }
/* WP auto-wraps CF7 fields in <p> and injects a <br> after the sr-only label.
   For dropdown rows the <br> adds a full line-height of empty space above the
   select — kill both so the row is exactly the select's height. */
.modal-form .ida-fg-full > p { margin: 0; }
.modal-form .ida-fg-full > p > br { display: none; }

/* ── Success confirmation ─────────────────────────────────────────────────
   After a successful CF7 submit inside the modal, the form body is hidden and
   this panel is revealed. Kept inside the same white card so the transition
   feels like a state swap, not a new modal. */
.modal-form.is-submitted .modal-form-body { display: none; }
.modal-form:not(.is-submitted) .modal-confirm { display: none; }
.modal-confirm[hidden] { display: none; }
.modal-form.is-submitted .modal-confirm[hidden] { display: block; }

.modal-confirm {
  padding: 44px 24px 32px;
  text-align: center;
  border-radius: 14px;
  background: rgba(226, 123, 39, 0.09);
  border: 1px solid rgba(226, 123, 39, 0.22);
}
.modal-confirm-icon {
  width: 68px;
  height: 68px;
  margin: 0 auto 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: rgba(226, 123, 39, 0.16);
  color: var(--ida-orange, #E27B27);
}
.modal-confirm-icon svg { width: 30px; height: 30px; }
.modal-confirm-title {
  font-size: clamp(22px, 2.4vw, 26px);
  line-height: 1.2;
  letter-spacing: -0.025em;
  color: #0F1116;
  margin: 0 0 10px;
}
.modal-confirm-msg {
  color: rgba(15, 17, 22, 0.72);
  font-size: 15px;
  line-height: 1.55;
  margin: 0 auto;
  max-width: 380px;
}

/* ============================================================
   §5 AD LANDING PAGE  (page-templates/template-landing.php)
   ============================================================
   Scoped entirely to .landing-* so nothing here can reach the rest of the
   site. Mobile first, per the page brief: the ad traffic
   arrives on a phone, and the layout is checked at 320px as well as 375px.

   Everything reuses the existing tokens and components (.glass, .pill,
   .smcaps, the type scale). The page has to look like it belongs on
   idasmiles.com, because a visitor who is weighing up the offer will click
   through to the rest of the site to check IDA out.
   ============================================================ */

/* ---------- Hero ---------- */
.landing-hero{
  background: var(--ida-navy-deep);
  /* 72px fixed header + breathing room. The merger banner does not run on
     this template, so no --merger-banner-h offset is needed. */
  padding: 160px 0 96px;
}
/* ---------- Accent colour on cream ----------
   .section-light .smcaps deepens the eyebrow to #C73D00, but nothing on the
   site reaches that rule: template-flexible.php renders every eyebrow with
   style="color: var(--hub-accent)" inline, which wins. Checked on
   /case-planning/, where all cream eyebrows compute to #F94E00 and none lacks
   the inline colour. The rule is a fallback, not a treatment.

   This page's eyebrows had no inline colour, so they were the only ones on the
   site landing on the fallback and reading muddy beside the FAQ plus/cross and
   the arrow bullets, which were brand orange all along. Restoring
   --hub-accent here matches the rest of the site rather than departing from it.

   For the record, since it is easy to assume otherwise: the brand orange the
   whole site uses is 3.02:1 on #F4F0E8 and 2.76:1 on #ECE6D8, under the 4.5:1
   WCAG AA asks of 11px text. The #C73D00 fallback would not fix that on the
   deeper cream either, reaching only 4.12:1. Raising it is a site-wide call,
   not something to solve on one page. */
body.is-landing .section-light .smcaps,
body.is-landing .section-light-alt .smcaps{ color: var(--hub-accent); }

/* The hero is a .hub-hero-grid again, copy left and form card right, so the
   column takes its width from the grid. The 70% cap that belonged to the
   single-column version is gone: inside a grid cell it squeezed the copy. */
.landing-hero-content{ min-width: 0; }
.landing-hero-terms{
  margin-top: 16px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--ida-text-mute);
}
/* Only renders if $form_shortcode is empty, which would be a build mistake. */
.landing-form-missing{ font-size: 13px; line-height: 1.5; color: #C73D00; }
/* The repeated call to action. Centred under the full-width blocks (the step
   cards, the estimator), left-aligned where it follows a column of copy. */
.landing-cta-row{ margin-top: 32px; }
.landing-cta-row--center{ margin-top: 44px; text-align: center; }
.landing-hero-sub{
  margin-top: 20px;
  font-size: 17px;
  line-height: 1.6;
  color: rgba(255,255,255,0.75);
  max-width: 560px;
}
/* ---------- Step cards: no hover ----------
   .glass:hover lifts the card and lays a purple-tinted gradient and purple
   border over it. That is designed for glass on a dark band; on a cream
   section .glass is already a solid WHITE card, so the hover reads as the card
   changing colour rather than responding.

   The homepage process band hit this first and the client flagged it, which is
   why #how .glass carries an override in this file. These are the same cards in
   the same situation, so they get the same treatment: the transition is
   removed, not just neutralised, so nothing animates on the way in either.

   Scoped to .section-light on purpose. The remake-comparison cards sit on navy,
   where the stock glass hover is correct. */
body.is-landing .section-light .glass{ transition: none !important; }
body.is-landing .section-light .glass:hover{
  transform: none !important;
  border-color: rgba(16,24,32,0.10) !important;
  background: #FFFFFF !important;
  box-shadow: 0 1px 0 rgba(16,24,32,0.04), 0 12px 32px -16px rgba(16,24,32,0.10) !important;
}

/* ---------- Reversed accent bands ----------
   Two sections run as .section-accent fills. The component already handles the
   pill; these are the parts it does not know about.

   The flat highlight inverts: an accent-coloured block on an accent-coloured
   background is invisible, so it becomes a white block with accent text, which
   is exactly what .section-accent already does to .pill. */
body.is-landing .section-accent .hl-flat{
  background: #ffffff;
  color: var(--hub-accent);
}
/* The capabilities columns reverse their ink and their rules. */
body.is-landing .section-accent .landing-strip-col{ border-top-color: rgba(255,255,255,0.45); }
body.is-landing .section-accent .landing-strip-label{ color: #ffffff; }
body.is-landing .section-accent .landing-strip-body{ color: #ffffff; }

/* ---------- Value strip ----------
   White on brand orange measures 3.43:1. That is under the 4.5:1 AA asks of
   body text but over the 3:1 it allows for large text, which WCAG defines as
   18.66px AND bold. 19px/700 is therefore the floor here, not a style
   preference: drop either and the strip stops being legible enough to pass. */
.landing-vp-band{
  background: var(--ida-orange);
  color: #ffffff;
  padding: 30px 0;
}
.landing-vp-list{
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  list-style: none;
  margin: 0;
  padding: 0;
}
/* The FAQ's jump to the turnaround table was a hard cut, which on a long page
   reads as the page having reloaded rather than moved. Smooth scrolling has to
   sit on the scrolling element, so it is hung off html via :has() rather than
   body.is-landing, keeping it to this page; the stylesheet already uses :has()
   elsewhere for the same reason.

   The reduced-motion block further down sets html { scroll-behavior: auto }
   with !important, which beats this on specificity grounds regardless of the
   :has(), so anyone who asks for less motion still gets the instant jump. */
html:has(body.is-landing){ scroll-behavior: smooth; }

/* Links inside a FAQ answer. .faq-a-inner sets a muted colour and nothing in
   the stylesheet styles an <a> inside it, so both links in this page's FAQ, the
   turnaround jump and the phone number, rendered as plain body text with no
   signal that they were clickable at all.

   Accent plus an underline, so it does not rely on colour alone. Brand orange
   on cream is 3.02:1, under the 4.5:1 AA asks of 16px text; the underline
   carries the affordance, and the accent matches the rest of the page per the
   native-brand-colour call. #C73D00 would reach 4.51:1 if legibility beats
   consistency here. */
body.is-landing .faq-a-inner a{
  color: var(--hub-accent);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: color .2s ease;
}
body.is-landing .faq-a-inner a:hover{ color: #0F1116; }

/* The FAQ links down to the turnaround table. Without a scroll margin the
   section lands flush at the viewport top and the 72px fixed header covers its
   heading. The site's own anchor sections use 140px, which allows for the
   /about/ sub-nav as well; this page has none, so 100px is enough. */
#turnaround{ scroll-margin-top: 100px; }

/* Pastel #7: icon above each callout, stroked in currentColor so it inherits
   the band's white. */
.landing-vp-icon{
  display: block;
  margin-bottom: 10px;
  line-height: 0;
}
.landing-vp-text{ display: block; }
.landing-vp-point{
  min-width: 0;
  padding: 14px 0;
  font-size: 19px;
  font-weight: 700;
  line-height: 1.35;
  letter-spacing: -0.01em;
}
.landing-vp-point + .landing-vp-point{
  border-top: 1px solid rgba(255,255,255,0.28);
}
@media (min-width: 768px){
  .landing-vp-list{ grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .landing-vp-point{ padding: 0 32px; }
  .landing-vp-point + .landing-vp-point{
    border-top: 0;
    border-left: 1px solid rgba(255,255,255,0.32);
  }
  .landing-vp-point:first-child{ padding-left: 0; }
  .landing-vp-point:last-child{ padding-right: 0; }
}

/* ---------- Remake comparison (gated section) ---------- */
.landing-compare{
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 16px;
}
.landing-compare-card{ padding: 28px 24px; }
.landing-compare-card--ida{ border-color: rgba(53,213,47,0.45); }
.landing-compare-rate{
  display: block;
  font-size: 11px; letter-spacing: 0.32em; text-transform: uppercase;
  color: var(--ida-text-mute); font-weight: 500;
}
.landing-compare-figure{
  display: block; margin-top: 10px;
  font-size: 34px; line-height: 1; font-weight: 700; letter-spacing: -0.035em;
  color: #fff;
}
.landing-compare-card--ida .landing-compare-figure{ color: var(--ida-green); }
.landing-compare-label{
  display: block; margin-top: 8px;
  font-size: 15px; color: rgba(255,255,255,0.70);
}
.landing-smallprint{
  margin-top: 24px;
  font-size: 12px; line-height: 1.6;
  color: var(--ida-text-dim);
  max-width: 560px;
}

/* ---------- Steps ---------- */
/* The cards themselves are the shared process_steps markup (.glass + Tailwind
   utilities), so there is nothing to style here. Only the two bits that layout
   does not carry: the reviewer flag inside a card, and the total-time line. */

/* ---------- Quotes ----------
   The carousel is the shared .testimonial-* component, so the only thing it
   needs here is the dark-background treatment: those arrows are coloured for
   the cream section the partial normally renders on. */
body.is-landing .testimonial-arrow{ color: rgba(255,255,255,0.72); }
body.is-landing .testimonial-arrow:hover{
  background: color-mix(in srgb, var(--hub-accent) 15%, transparent);
  border-color: var(--hub-accent);
  color: var(--hub-accent);
}

/* The shared carousel hides its arrows below 900px and has no swipe handler, so
   on a phone only the first of three quotes is reachable. That is tolerable on
   a page someone browses; it is not on an ad landing page where most of the
   traffic is mobile and this is the trust moment. Below 900px every quote
   renders, stacked, and the carousel becomes a plain list.

   Arrows stay hidden rather than shown: two 44px circles plus the flex gap take
   120px of a 375px screen, which leaves the quote too narrow to read. */
@media (max-width: 900px){
  body.is-landing .testimonial-slide{ display: block; }
  body.is-landing .testimonial-slide.is-active{ animation: none; }
  body.is-landing .testimonial-slide + .testimonial-slide{
    margin-top: 40px;
    padding-top: 40px;
    border-top: 1px solid var(--ida-line);
  }
  /* 48px above the author row is a lot when the quotes stack. */
  body.is-landing .testimonial-slide .mt-12{ margin-top: 1.75rem; }
}

/* ---------- Google reviews ---------- */
.landing-google{
  margin-top: 48px;
  padding-top: 40px;
  border-top: 1px solid var(--ida-line);
}
.landing-google-grid{
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 20px;
}
.landing-google-card{ margin: 0; min-width: 0; }
.landing-google-icon{
  display: block;
  margin-bottom: 12px;
  line-height: 0;
}
.landing-google-text{
  margin: 0;
  font-size: 14px; line-height: 1.6;
  /* Heavier and lighter than the 400/0.70 it started at: at 14px on navy that
     was the faintest text on the page, and these are proof, not small print. */
  font-weight: 500;
  color: rgba(255,255,255,0.82);
}
.landing-google-name{
  display: block; margin-top: 10px;
  font-size: 13px; font-weight: 600; color: rgba(255,255,255,0.88);
}

/* ---------- Turnaround ----------
   The table itself is the shared estimator partial (.ltt), which carries its
   own card, menu and controls. Only the line under it lives here. */
.landing-price-line{
  margin-top: 28px;
  text-align: center;
  font-size: 16px; line-height: 1.6;
  color: rgba(16,24,32,0.72);
}

/* ---------- What we make strip ---------- */
.landing-strip{
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 32px;
}
/* A rule above each column rather than between them. The three hold very
   unequal amounts of copy (a four-item list against a single sentence), so
   vertical dividers would draw the eye straight to the empty space under the
   short ones; a top rule gives each column the same clear start and lets the
   lengths differ without looking unfinished. */
.landing-strip-col{
  min-width: 0;
  border-top: 1px solid rgba(16,24,32,0.18);
  padding-top: 24px;
}
.landing-strip-label{
  display: block; margin-bottom: 14px;
  font-size: 11px; letter-spacing: 0.32em; text-transform: uppercase;
  color: var(--hub-accent); font-weight: 500;
}
.landing-strip-list{ list-style: none; margin: 0; padding: 0; }
/* Size, weight and colour come from the shared arrow-bullet markup inline, the
   same as "What you get". Only the spacing between rows belongs here. */
.landing-strip-list li + li{ margin-top: 14px; }
/* The prose columns take the bullets' type so the three columns read as one
   set. .font-display is weight 700, hence the weight here; tracking-tight is
   -0.025em, which beats .font-display's own -0.035em. */
.landing-strip-body{
  font-weight: 700;
  font-size: clamp(17px, 1.55vw, 20px);
  line-height: 1.3;
  letter-spacing: -0.025em;
  color: #0F1116;
}

/* ---------- Form ---------- */
.landing-form-wrap{
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 36px;
  align-items: start;
}
.landing-form-head{ min-width: 0; }
/* Headline inside each form card. .hub-hero-form sets the card's dark ink, so
   this only needs its spacing. */
.landing-form-title{ margin-bottom: 20px; }
.landing-form-sub{
  margin-top: 18px;
  font-size: 16px; line-height: 1.6;
  color: rgba(255,255,255,0.75);
  max-width: 480px;
}
.landing-form-phone{
  margin-top: 18px;
  font-size: 15px;
  color: rgba(255,255,255,0.75);
}
.landing-form-phone a{
  color: var(--ida-purple-bright);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 4px;
}
.landing-form-phone a:hover{ color: #fff; }
/* ---------- Tablet and up ---------- */
@media (min-width: 640px){
  .landing-compare{ grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .landing-google-grid{ grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (min-width: 1024px){
  .landing-hero{ padding: 224px 0 128px; }
  .landing-hero-sub{ font-size: 19px; }
  .landing-strip{ grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 40px; }
  .landing-form-wrap{ grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 56px; }
}

/* ---------- Narrow phones ----------
   320px is in the brief's QA list. The hero figure and the quote type both
   need to come down or they force a horizontal scroll. */
@media (max-width: 359px){
}
