/* ==========================================================================
   Design tokens — the single source of truth.
   Every colour is OKLCH and every text/background pair is verified against
   WCAG 2.2 AA by scripts/check_contrast.py, which fails the build if a pair
   drops below threshold. Do not introduce a raw colour anywhere else.
   ========================================================================== */

:root {
  /* --- Ground: the navy drench ------------------------------------------ */
  --bg:            oklch(0.148 0.058 264);
  --bg-raised:     oklch(0.212 0.084 264);   /* the brand navy */
  --bg-raised-2:   oklch(0.272 0.088 263);
  --bg-page:       oklch(0.986 0.004 250);   /* reading surface, tinted to the brand's
                                                own blue — never toward warm */
  --bg-page-2:     oklch(0.962 0.007 250);

  /* --- Ink --------------------------------------------------------------- */
  --ink:            oklch(0.984 0.005 250);  /* 17.0:1 on brand navy */
  --ink-soft:       oklch(0.820 0.032 250);  /* 10.2:1 */
  --ink-dark:       oklch(0.205 0.032 264);  /* 17.2:1 on reading surface */
  --ink-dark-soft:  oklch(0.415 0.030 262);  /*  8.3:1 */

  /* --- Gold, as a material ----------------------------------------------- *
   * --gold measures 1.93:1 on --bg-page. It is never text on a light
   * surface. --gold-deep is the only gold that may be.                      */
  --gold:          oklch(0.780 0.112 85);
  --gold-bright:   oklch(0.905 0.098 96);
  /*
   * 0.500, not 0.535. The old value was verified against --bg-page only (5.02:1)
   * and passed, but the light world has three grounds and it measured just
   * 4.36:1 against the deepest well (--bg-raised-2), which is where the
   * reassurance attribution and the lit face actually sit. This clears 4.5 on
   * all three: 5.83 / 5.44 / 5.06.
   */
  --gold-deep:     oklch(0.500 0.104 82);
  --gold-ink:      oklch(0.860 0.100 90);    /* 11.6:1 on brand navy */

  /* --- Sky: cool relief, used sparingly ---------------------------------- */
  --sky:           oklch(0.720 0.098 232);
  --sky-dim:       oklch(0.545 0.088 235);   /* 4.7:1 on --bg-page */
  --sky-wash:      oklch(0.945 0.028 225);

  /* --- Lines and shadow --------------------------------------------------- */
  --rule:          oklch(0.360 0.070 262);
  --rule-light:    oklch(0.900 0.010 250);
  --rule-strong:   oklch(0.460 0.080 261);

  /* --- Edges: the cut-lines of a plane ------------------------------------ *
   * Three values, declared LITERALLY. This replaces nine arbitrary gold
   * opacities (22/24/26/28/30/32/35/40/45%) that were used interchangeably for
   * what is visually one line.
   *
   * They are literals rather than color-mix() for a reason worth recording:
   *   color-mix(in oklch, var(--gold) 55%, var(--bg))
   * resolves to oklch(0.4956 0.0877 165.55) — #247256, a SEA GREEN. OKLCH
   * interpolates hue along the short arc, and the short arc from gold (H85) to
   * navy (H264) runs straight through green. Mixing gold toward `transparent`
   * is safe (hue is preserved under premultiplication) and the rest of this
   * codebase only ever does that; mixing gold into an opaque navy is not.
   *
   * --edge is the only value legal as the SOLE carrier of a division
   * (SC 1.4.11 wants 3:1). --edge-dim is decorative and must always have
   * something else carrying the boundary.                                    */
  --edge-dim:      oklch(0.360 0.055 85);   /* 1.82:1 on --bg — decorative only */
  --edge:          oklch(0.520 0.085 85);   /* 3.57:1 on --bg, 3.22:1 on --bg-raised */
  --edge-lit:      oklch(0.780 0.112 85);   /* 9.84:1 — active / hover / focus */

  /* The focus ring follows its ground; --gold is 1.93:1 on light and illegal there. */
  --ring:          oklch(0.780 0.112 85);   /* 9.84:1 on navy */
  --ring-halo:     oklch(0.780 0.112 85 / 0.30);

  --shadow-near:   0 1px 2px oklch(0.148 0.058 264 / 0.28);
  --shadow-lift:   0 12px 32px -12px oklch(0.148 0.058 264 / 0.45);
  --shadow-deep:   0 32px 80px -28px oklch(0.100 0.050 264 / 0.70);
  --glow-gold:     0 0 0 1px oklch(0.780 0.112 85 / 0.45),
                   0 8px 40px -12px oklch(0.780 0.112 85 / 0.40);

  /* --- Type -------------------------------------------------------------- */
  --font-display: "Young Serif", ui-serif, Georgia, "Times New Roman", serif;
  --font-text:    "Schibsted Grotesk", ui-sans-serif, system-ui, -apple-system,
                  "Segoe UI", Roboto, sans-serif;

  /*
   * Scaled down against the reference site.
   *
   * The previous ceilings were display 88px and h2 56px, which at 1440 made every heading
   * shout and pushed the home page to 20,000px on a phone. Measured against
   * restorativedentistrygroup.com the whole ratio was running roughly a third large.
   * Ceilings now: display 64px, h2 40px, h3 28px — editorial rather than billboard, and
   * the fluid floors come down with them so phones gain the most.
   *
   * Body is 16px. The old note here defended 17px against a 15px strawman; 16px is the
   * web's reading default and the smaller headings mean the hierarchy still reads.
   */
  --t-display: clamp(2.25rem,  1.50rem + 3.30vw, 4.00rem);   /* 36 → 64px */
  --t-h2:      clamp(1.75rem,  1.30rem + 1.90vw, 2.50rem);   /* 28 → 40px */
  --t-h3:      clamp(1.35rem,  1.15rem + 0.85vw, 1.75rem);   /* 21.6 → 28px */
  --t-h4:      clamp(1.10rem,  1.02rem + 0.38vw, 1.30rem);   /* 17.6 → 20.8px */
  --t-lead:    clamp(1.05rem,  1.00rem + 0.26vw, 1.1875rem); /* 16.8 → 19px */
  --t-body:    1rem;        /* 16px */
  --t-small:   0.9375rem;   /* 15px — secondary copy, never the main read */
  /*
   * 14px, not 13px, and it is a LABEL size — never a sentence.
   *
   * This practice fits dentures, places implants and treats three generations of
   * the same family; a meaningful share of the people reading this are over
   * sixty, and several of them told us in their own reviews that they had put
   * off a dentist for a decade. Six different classes were setting real reading
   * copy at 13px: what you will feel in the chair, which languages each dentist
   * speaks, what happens if you cannot pay. None of that is fine print.
   */
  --t-micro:   0.875rem;    /* 14px — labels, never running text */

  --lh-display: 1.02;
  --lh-heading: 1.14;
  --lh-body:    1.62;
  --lh-body-dark: 1.68;   /* light type on dark reads lighter; give it room */

  --ls-display: -0.02em;
  --ls-heading: -0.012em;
  --ls-body:    0;

  --measure:      68ch;
  --measure-tight: 54ch;

  /* --- Space: varied for rhythm, not a uniform ladder --------------------- */
  --s-3xs: 0.25rem;
  --s-2xs: 0.5rem;
  --s-xs:  0.75rem;
  --s-sm:  1rem;
  --s-md:  1.5rem;
  --s-lg:  2.25rem;
  --s-xl:  3.5rem;
  --s-2xl: 5rem;
  --s-3xl: 7.5rem;

  --section-y:       clamp(3.25rem, 2.25rem + 4.2vw, 6rem);
  --section-y-tight: clamp(2.25rem, 1.6rem + 2.8vw, 4rem);
  --gutter:          clamp(1.25rem, 0.75rem + 2.2vw, 3rem);

  /* Height of the credential plane that straddles the hero's bottom edge. It
     lives here rather than on the component because three rules have to agree
     on it: the plane's own height, the lift that centres it on the seam, and
     the bottom padding the hero uses to reserve room for it.

     Flat, not a clamp, and that is the point. The lift is half of THIS value,
     so the moment the plane's real height exceeds it the overlap stops being
     centred — at 1024px the phrases wrap to two lines, the plane grew to 110px
     against an 80px token, and the split drifted to 36/64. 7.5rem clears the
     two-line case at the narrowest width the bridge is used at, which keeps
     the arithmetic true everywhere above it. Raised to 8.75rem when each face
     gained a display-serif lead over a qualifier; tools/bridge-check.mjs is
     what says whether a number here is still big enough. */
  /* The clamp runs BACKWARDS on purpose: bigger at narrow widths, smaller at
     wide ones. The faces are a fifth of the container each, so the narrower the
     viewport the more likely "English · Español · Português" wraps to a second
     line and the taller the plane really is. A normal forward clamp gives the
     smallest token exactly where the content is tallest, which is how the split
     drifted to 43/57 at 1024px while measuring 49/51 everywhere else. */
  --bridge-h:        clamp(8.5rem, 11rem - 1.5vw, 10.25rem);
  /*
   * Viewport-relative with a cap, not a flat cap.
   *
   * A fixed rem width stops growing the moment the screen passes it, so the content's
   * share of the screen collapses as the monitor gets bigger — measured at 80.6% of a
   * 1440 viewport, 62.2% of 1920 and 48.2% of 2560. Less than half the screen in use, and
   * the page read as a column floating in the middle of a lot of nothing.
   *
   * `min(vw, cap)` keeps the proportion roughly constant instead: the vw term governs
   * across normal desktops, and the cap only ever catches the extreme. Reading width is a
   * separate problem with a separate token — see --container-read, and the measure caps
   * on the prose blocks in layout.css. This one holds grids, not paragraphs.
   */
  --container:       min(95vw, 100rem);
  --container-wide:  min(97vw, 110rem);
  --container-read:  46rem;

  /* --- Motion ------------------------------------------------------------- */
  --ease-out:  cubic-bezier(0.16, 1, 0.30, 1);      /* expo — the house curve */
  --ease-soft: cubic-bezier(0.32, 0.72, 0.24, 1);
  --ease-in:   cubic-bezier(0.55, 0, 1, 0.45);

  --dur-fast: 160ms;
  --dur-mid:  320ms;
  --dur-slow: 620ms;
  --dur-reveal: 900ms;

  /* --- Z-index: semantic, never arbitrary --------------------------------- */
  --z-base:      0;
  --z-raised:    10;
  --z-sticky:    100;
  --z-nav:       200;
  --z-backdrop:  300;
  --z-modal:     400;
  --z-toast:     500;

  /* --- The facet -----------------------------------------------------------
   * Drawn from the diamond in the practice's mark: corners cut unevenly so the
   * shape reads as a cut stone rather than a chamfered rectangle. Every
   * photograph on the site is clipped with one of these.                     */
  --facet:       polygon(0 6%, 7% 0, 100% 0, 100% 92%, 93% 100%, 0 100%);
  --facet-flip:  polygon(0 0, 93% 0, 100% 8%, 100% 100%, 7% 100%, 0 94%);
  /* Deliberately off-axis. A symmetrical hexagon reads as a gem *icon*; skewing the
     crown makes it read as a stone seen from a viewpoint, which is quieter and less
     literal behind a photograph of a real family. */
  --facet-crown: polygon(44% 0, 100% 17%, 100% 79%, 56% 100%, 0 84%, 0 21%);
  --facet-soft:  polygon(0 3.5%, 4% 0, 100% 0, 100% 96.5%, 96% 100%, 0 100%);

  /* The cut used on ASSEMBLIES rather than on photographs. Parametric in px, not
     percent: a percentage chamfer is right on a photo because it scales with the
     crop, but on a wide short plane it stretches into a long shallow slash. 20px
     is smaller than the 36px face padding, so the cut can never clip a word —
     including at 200% zoom. */
  --cut:         1.25rem;
  --cut-plane:   polygon(
                   0 var(--cut), var(--cut) 0, 100% 0,
                   100% calc(100% - var(--cut)), calc(100% - var(--cut)) 100%, 0 100%);

  /* --- How much smaller the INNER face's cut is than the frame's -------------
   * A cut assembly is built as a frame element that paints gold, with the face
   * inset by P = 2px of padding on every side. On the four straight sides that
   * inset IS the gold band: 2px, done. The two diagonals need arithmetic, and
   * getting the sign wrong there is why the chips shipped three times with
   * "missing" corners.
   *
   * Work in the frame's own coordinates. Its diagonal is the line x + y = cut.
   * The face is translated by (P, P), so a face cut of `c` puts the face's
   * diagonal at x + y = c + 2P. The perpendicular distance between two lines
   * x + y = a and x + y = b is |a - b| / sqrt2, so the visible gold is
   *
   *     G = (c + 2P - cut) / sqrt2          and therefore
   *     c = cut - 2P + G*sqrt2
   *
   * The face's cut is SMALLER than the frame's, but only by a hair — and the
   * earlier derivation lost the sign on the G*sqrt2 term, which turned a small
   * subtraction into a large one. At P = 2 the chips asked for `cut - 6.85px`,
   * which is c = cut - 2P - P*sqrt2: the face then overhangs the frame's own
   * clip by 2.02px, gets cut off by it, and the gold along both diagonals is
   * not thin, it is exactly zero. Measured on the shipped page: R-B of 122 on
   * all four straight sides and 3 on the diagonals, which is the face colour.
   *
   * G = 2.4px, a touch heavier than the 2px straight sides, because a 45 degree
   * band is antialiased across its whole length and reads lighter than a
   * perpendicular one at equal width.
   *
   *     c = cut - 4 + 2.4*sqrt2 = cut - 0.606
   *
   * One token, so the frame and the chip can never drift apart again — they
   * already had: the plane's two corners were authored at 3px and 1.5px, which
   * is 0.71px of gold at one corner and 1.77px at the other.                  */
  --facet-back:  0.606px;

  /* The gold leaf rule's gradient, held once. It is drawn both as a real <hr class="leaf-rule">
     and as a ::after on section headings, and two copies of a five-stop gradient is how a
     motif ends up subtly different in the two places it appears. */
  --leaf: linear-gradient(90deg,
            color-mix(in oklch, var(--gold) 8%, transparent) 0%,
            color-mix(in oklch, var(--gold) 55%, transparent) 22%,
            var(--gold-bright) 46%,
            color-mix(in oklch, var(--gold) 45%, transparent) 68%,
            color-mix(in oklch, var(--gold) 6%, transparent) 100%);

  --radius-sm: 3px;
  --radius-md: 5px;   /* the design leans on facets, not on rounding */

  --header-h: 4.75rem;
  --actionbar-h: 4.25rem;   /* mobile call/book bar — the page reserves this */
}

/* --- Large screens -------------------------------------------------------
 * At 2560px the 78rem container filled 45% of the viewport and the page read
 * as mostly empty navy — one whole 2560x1200 screenful of nothing between
 * sections. The fix is not simply "wider": a 2000px measure is unreadable.
 *
 * Instead the root font-size steps up, so type, spacing and the container all
 * scale together in the same proportion. The line length in *characters*
 * stays where it was; the page just gets bigger, the way it does on a bigger
 * sheet of paper.
 * -------------------------------------------------------------------------- */

@media (min-width: 100rem) {          /* ~1600px */
  :root {
    font-size: 16.5px;
    --container: min(92vw, 120rem);
    --container-wide: min(95vw, 132rem);
    /* 5vw was 96px of gutter at 1920 and 128px at 2560 — a third of the margin the page
       was losing came from here rather than from the container. */
    --gutter: clamp(2.5rem, 3.5vw, 5rem);
  }
}

@media (min-width: 128rem) {          /* ~2048px — ultrawide territory */
  :root {
    font-size: 17.5px;
    --container: min(90vw, 140rem);
    --container-wide: min(94vw, 152rem);
    --gutter: clamp(3rem, 3.5vw, 6rem);
    --section-y: clamp(4rem, 3rem + 3.5vw, 7.5rem);
  }
}

/* ==========================================================================
   The two grounds.

   Each is defined ONCE and can be entered either by the <body> (the template's
   world, set in inc/setup.php) or by an individual section. A section modifier
   is authoritative: it restates the whole token set rather than inheriting.

   That matters. Before this, `.section--navy` only said
   `background: var(--bg-raised)`, and on any page whose body carried .t-light —
   every archive, the blog, search — .t-light had already redefined --bg-raised
   to the near-white value, so the navy sections on those pages silently
   rendered light. The services archive showed it the moment that page started
   rendering at all.
   ========================================================================== */

.t-dark,
.section--navy,
.section--deep {
  --bg:          oklch(0.148 0.058 264);
  --bg-raised:   oklch(0.212 0.084 264);
  --bg-raised-2: oklch(0.272 0.088 263);
  --ink:         oklch(0.984 0.005 250);
  --ink-soft:    oklch(0.820 0.032 250);
  --gold-ink:    oklch(0.860 0.100 90);
  --sky:         oklch(0.720 0.098 232);
  --rule:        oklch(0.360 0.070 262);
  --rule-strong: oklch(0.460 0.080 261);
  --lh-body:     var(--lh-body-dark);

  --edge-dim:    oklch(0.360 0.055 85);
  --edge:        oklch(0.520 0.085 85);
  --edge-lit:    oklch(0.780 0.112 85);
  --ring:        oklch(0.780 0.112 85);
  --ring-halo:   oklch(0.780 0.112 85 / 0.30);

  color: var(--ink);
}

.t-light,
.section--light {
  --bg:          var(--bg-page);
  --bg-raised:   var(--bg-page-2);
  --bg-raised-2: oklch(0.938 0.009 250);
  --ink:         var(--ink-dark);
  --ink-soft:    var(--ink-dark-soft);
  --gold-ink:    var(--gold-deep);
  --sky:         var(--sky-dim);
  --rule:        var(--rule-light);
  --rule-strong: oklch(0.820 0.014 250);
  --lh-body:     1.65;

  /* Gold cannot carry a boundary on near-white: --gold is 1.93:1 there at ANY
     alpha. The structural edge on light is a dark neutral; gold appears only as
     the one lit gesture per section, and only at full strength. */
  --edge-dim:    oklch(0.880 0.010 250);   /* 1.38:1 — decorative only */
  --edge:        oklch(0.600 0.014 250);   /* 3.79:1 on --bg-page — structural */
  --edge-lit:    var(--gold-deep);         /* 5.02:1 — the brand gesture */

  --ring:        var(--gold-deep);         /* 5.02:1; --gold would be 1.93:1 */
  --ring-halo:   oklch(0.535 0.104 82 / 0.28);

  color: var(--ink);
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-fast: 1ms;
    --dur-mid: 1ms;
    --dur-slow: 1ms;
    --dur-reveal: 1ms;
  }
}
