/* ==========================================================================
   Surfaces — the replacement for "1px border + 5px radius + var(--s-lg) padding".

   That single recipe was used by sixteen different panels, with nine arbitrary
   gold border opacities between them, and fourteen of them had no hover state
   at all. Twenty-six named components resolved to three recipes. The page read
   as a list of interchangeable boxes because it was one.

   There are now FOUR surfaces, and the choice between them is determined by
   what the content IS, not by how it should look:

     BARE   no container at all. Type on the ground, separated by space and,
            where a division is needed, a rule sized to the text.
            Use for anything primarily READ. This should be the majority.

     FACE   a region of a cut plane (below). Never used alone — a face only
            exists as part of a set of three or more equal siblings.

     WELL   a recessed tint for things you read but do not act on: insurer
            lists, opening hours, addresses, disclaimers.

     INLAY  a navy panel inside a light section. The single most important
            object on a page — the emergency band, the price answer. One per
            page, at most. This is where gold is legal at full strength.

   THE LAW: containment must be earned. A container exists only when the
   content is a different KIND of thing from the page around it, is interactive
   as a single unit, or is the one object that must dominate. Prose is never a
   different kind of thing from the page.
   ========================================================================== */

/* --- THE CUT PLANE --------------------------------------------------------
 * A multi-item section is ONE surface, not N cards. The container paints the
 * cut-line colour as its own background and the faces sit on it with a 1px
 * grid gap, so the line between any two faces is a single shared edge that
 * cannot desynchronise, and no face owns a border, a radius, a shadow or a
 * margin.
 *
 * The faces stay EQUAL. Unequal faces would carry more information, but the
 * client rejected asymmetry across the whole site after seeing it, so the
 * variation here comes from the ground, the cut and the content instead.
 * -------------------------------------------------------------------------- */

.plane {
  position: relative;
  isolation: isolate;
  display: grid;
  gap: 2px;
  padding: 2px;
  background: var(--edge);
  clip-path: var(--cut-plane);
  /*
   * `clip` rather than `hidden`, and it is load-bearing.
   *
   * The rake in motion.css gives `.plane::after` `inset: -30% -60%` — ±979px on a 1632px
   * track — and slides it ±55%. `clip-path` above already stops that painting outside the
   * plane, which is why it looked fine, but clip-path is a PAINT operation: it does not
   * touch the scrollable overflow area. So the document quietly grew to 3678px wide at
   * 1440 and the page scrolled 1611px sideways into blank space, on every desktop, as soon
   * as a reader had scrolled the testimonials band past. `body { overflow-x: clip }` in
   * base.css did not contain it either.
   *
   * `overflow: clip` removes the descendants from the scrollable overflow region, which is
   * the actual defect. `hidden` would also work and would additionally make this a scroll
   * container, which breaks `position: sticky` for anything inside it — a trade nothing
   * here needs to make.
   *
   * Verified safe before applying: across all six routes that carry a plane, the only
   * descendant painting beyond its own box is `.tour__play`'s drop shadow, which sits in
   * the middle of a video frame and cannot reach an edge. Focus rings inside a plane use
   * `outline-offset: -4px` (see below), so they draw inward and cannot be clipped.
   */
  overflow: clip;
}

.plane > * {
  position: relative;
  min-width: 0;
  background: var(--face, var(--bg-raised));
  padding: var(--s-lg);
  transition: background-color var(--dur-mid) var(--ease-out);
}

.section--light .plane,
.t-light .plane { --face: var(--bg-page); }

/* Column counts are authored per section, never auto-fit — auto-fit is what
   produced a five-card row that reflowed to 3 + 2 and looked like a mistake. */
.plane--2 { grid-template-columns: 1fr; }
.plane--3 { grid-template-columns: 1fr; }
.plane--4 { grid-template-columns: 1fr; }
@media (min-width: 40rem) {
  .plane--2 { grid-template-columns: repeat(2, 1fr); }
  .plane--4 { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 60rem) {
  .plane--3 { grid-template-columns: repeat(3, 1fr); }
  .plane--4 { grid-template-columns: repeat(4, 1fr); }
}

/* Five is the awkward one: it divides into nothing. Two columns would leave a
   2 + 2 + 1 with a hole beside the last face, which is exactly the ragged edge
   the client rejected — so the odd one out takes the full width instead, and
   the run stays a solid rectangle at every step. */
.plane--5 { grid-template-columns: 1fr; }
@media (min-width: 40rem) {
  .plane--5 { grid-template-columns: repeat(2, 1fr); }
  .plane--5 > :nth-child(5) { grid-column: 1 / -1; }
}
@media (min-width: 64rem) {
  .plane--5 { grid-template-columns: repeat(5, 1fr); }
  .plane--5 > :nth-child(5) { grid-column: auto; }
}

/* Equal-height rows, so the shared edges form one continuous grid rather than
   a ragged one. */
.plane { grid-auto-rows: 1fr; }

/*
 * The cut corners get their gold edge back.
 *
 * The plane's outline is its own 1px padding showing through from behind the
 * faces. `clip-path` then removes a 20px triangle at two corners — and it cuts
 * through the padding AND the face together, so along those two diagonals the
 * face's background sat flush against the clip edge and there was no gold at
 * all. Every plane read as a box whose border broke at the corners.
 *
 * The corner faces are therefore clipped SHORT of the plane's own diagonal, so
 * the same band of gold runs along the cut as along every straight edge.
 *
 * `--facet-back` is that offset, derived in tokens.css and shared with the
 * facet chips so the two constructions cannot drift. They already had, and so
 * had the two corners of this very rule: authored at 3px and 1.5px, they were
 * putting 0.71px of gold at the top-left and 1.77px at the bottom-right of the
 * same plane. `--cut` is in px, so this stays uniform at any plane size.
 */
.plane > :first-child {
  clip-path: polygon(
    0 calc(var(--cut) - var(--facet-back)), calc(var(--cut) - var(--facet-back)) 0,
    100% 0, 100% 100%, 0 100%);
}
.plane > :last-child {
  clip-path: polygon(
    0 0, 100% 0,
    100% calc(100% - var(--cut) + var(--facet-back)),
    calc(100% - var(--cut) + var(--facet-back)) 100%,
    0 100%);
}

/*
 * ONE face is both the first and the last, and the two rules above cannot both apply.
 *
 * `:first-child` sets the top-left cut and `:last-child` sets the bottom-right; on a plane
 * with a single face they match the same element and the later rule simply overwrites the
 * earlier one's `clip-path`. So the face kept its square top-left corner, poked past the
 * frame's own diagonal there, and was cut off by it — no gold on that corner at all, which
 * is the same failure the chips had, reappearing through a different door.
 *
 * A single face needs both cuts in one polygon. Measured: cut-tl went from 291 units off the
 * frame colour to 0.
 */
.plane > :only-child {
  clip-path: polygon(
    0 calc(var(--cut) - var(--facet-back)), calc(var(--cut) - var(--facet-back)) 0,
    100% 0,
    100% calc(100% - var(--cut) + var(--facet-back)),
    calc(100% - var(--cut) + var(--facet-back)) 100%,
    0 100%);
}

/* A single-column plane stacks, so the first and last faces are the full width
   and the cut belongs to the same two corners of the whole run. */
@media (max-width: 39.99rem) {
  .plane > :first-child,
  .plane > :last-child { clip-path: none; }
  .plane { clip-path: none; }
}

/*
 * clip-path clips the OUTLINE of every descendant, so a normal focus ring on a
 * face is drawn outside the clip and disappears entirely — a WCAG 2.4.7
 * failure. Verified in the browser: with `outline-offset: 3px` the ring was
 * completely invisible; drawn inward it is unmistakable. Non-negotiable.
 */
.plane :focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: -4px;
  box-shadow: inset 0 0 0 6px var(--ring-halo);
  border-radius: 0;
}

/* Hover lights the face's own ground and its shared edges. Nothing translates:
   a face cannot lift off a plane it is cut from. */
/*
 * A face can hold a second action beside its main link (the emergency face carries a
 * phone number). So the face itself is the column, and only the FIRST child anchor is the
 * card link — scoping this as `> a` instead caught the phone button too and stretched it
 * to the full height of the face, where the plane's clip-path hid it completely.
 */
.plane > .face--link {
  padding: 0;
  display: flex;
  flex-direction: column;
}
.plane > .face--link > .face__link {
  display: flex;
  flex-direction: column;
  gap: var(--s-sm);
  flex: 1;
  padding: var(--s-lg);
  text-decoration: none;
  color: inherit;
}
.plane > .face--link:hover { background: var(--bg-raised-2); }
.section--light .plane > .face--link:hover,
.t-light .plane > .face--link:hover { background: var(--bg-page-2); }

/*
 * A LIT face. One per plane at most: the face that must be found rather than browsed —
 * on the services plane that is emergencies, because the person who needs it is in pain
 * and is not reading a list. It is marked by the ground and by a gold top edge, never by
 * a coloured left border.
 */
.plane > .face--lit {
  --face: var(--bg-page-2);
  box-shadow: inset 0 3px 0 var(--edge-lit);
}
.t-dark .plane > .face--lit,
.section--navy .plane > .face--lit,
.section--deep .plane > .face--lit { --face: var(--bg-raised-2); }

.services__call {
  display: block;
  margin: 0 var(--s-lg) var(--s-lg);
  padding: 0.6rem 0.9rem;
  text-align: center;
  font-size: var(--t-small);
  font-weight: 600;
  text-decoration: none;
  /* Literal navy. `var(--bg)` here resolved to the near-white reading surface,
     because this button lives inside a light section — near-white on gold is
     1.93:1. Ink on a fixed-colour ground must itself be fixed. */
  color: oklch(0.148 0.058 264);
  background: var(--gold);
  clip-path: var(--facet-soft);
}
.services__call:hover { background: var(--gold-bright); }

/* --- WELL -----------------------------------------------------------------
 * Recessed rather than raised, with no border. A single inner hairline along
 * the top edge so the light appears to fall INTO it, which is what separates
 * it from a raised panel without needing an outline.                        */

.well {
  background: var(--bg-raised-2);
  padding: var(--s-lg);
  box-shadow: inset 0 1px 0 var(--edge);
  clip-path: var(--facet-soft);
}
.section--light .well,
.t-light .well { background: var(--bg-page-2); }

/* --- INLAY ----------------------------------------------------------------
 * The one object per page that must dominate. Always navy, even inside a light
 * section — which is exactly why it dominates — and the only surface where
 * gold is legal at full strength.                                            */

.inlay {
  /*
   * A LITERAL navy, not var(--bg-raised).
   *
   * An inlay lives inside a light section, and .section--light has already
   * redefined --bg-raised to the near-white well colour — so painting from the
   * token gave a light panel wearing the inlay's white ink, i.e. white text on
   * near-white. The whole point of this surface is that it does not follow its
   * surroundings, so it cannot read its ground from them.
   */
  background: oklch(0.212 0.084 264);
  color: oklch(0.984 0.005 250);
  padding: var(--s-xl) var(--s-lg);
  clip-path: var(--cut-plane);

  --bg:        oklch(0.148 0.058 264);
  --bg-raised: oklch(0.212 0.084 264);
  --ink:       oklch(0.984 0.005 250);
  --ink-soft:  oklch(0.820 0.032 250);
  --gold-ink:  oklch(0.860 0.100 90);
  --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);
}

/* --- BARE -----------------------------------------------------------------
 * Not a class so much as the absence of one. `.bare-set` is only here to give
 * a list of read-only items its spacing and its text-width rule, so that the
 * majority of the site's content can stop being boxes.                       */

.bare-set {
  display: grid;
  gap: var(--s-xl) var(--s-2xl);
}
@media (min-width: 48rem)  { .bare-set--2 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 60rem)  { .bare-set--3 { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 72rem)  { .bare-set--5 { grid-template-columns: repeat(5, 1fr); } }

.bare-set > li > h3,
.bare-set > li > h4 { margin-block-end: var(--s-2xs); }
.bare-set > li > p  { color: var(--ink-soft); font-size: var(--t-small); }

/* The rule is sized to the TEXT, not to a container — the tell of a bare
   surface is that nothing is boxed, so the only geometry is the type's own. */
.bare-set > li::before {
  content: "";
  display: block;
  width: 2.5rem;
  height: 2px;
  margin-block-end: var(--s-sm);
  background: linear-gradient(90deg, var(--edge-lit), transparent);
}

/* ==========================================================================
   Interaction — what the surfaces do under a pointer.

   Fourteen of the sixteen original panel types had no hover state at all, so
   the page felt inert: nothing acknowledged the cursor and nothing indicated
   what was clickable. Everything below is transform/opacity/colour only, so it
   composites, and every one of them is suppressed under reduced motion.

   The rule: a face reacts by LIGHTING, never by lifting. A face is cut from a
   plane — it cannot float off the stone it belongs to. Only free objects
   (buttons, the booking modal) are allowed to move in Z.
   ========================================================================== */

/* --- A face lights along its cut edge ------------------------------------ */

.plane > .face {
  position: relative;
}
.plane > .face::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur-mid) var(--ease-out);
  /* A gold wash pooling from the top edge, as if the lamp moved closer. */
  background: linear-gradient(180deg,
    color-mix(in oklch, var(--gold) 12%, transparent) 0%,
    transparent 45%);
}
.plane > .face--link:hover::after,
.plane > .face--link:focus-within::after { opacity: 1; }

/* --- The arrow on any link that has one ---------------------------------- */

.btn__arrow { transition: transform var(--dur-mid) var(--ease-out); }
a:hover > .btn__arrow,
a:hover .btn__arrow,
.face--link:hover .btn__arrow { transform: translateX(0.28rem); }

/* --- Quotes: the mark warms, the rule draws ------------------------------ */

.quote { position: relative; }
.quote .stars { transition: transform var(--dur-mid) var(--ease-out); }
.quote:hover .stars { transform: scale(1.06); transform-origin: left center; }
.quote__meta { transition: border-color var(--dur-mid) var(--ease-out); }
.quote:hover .quote__meta { border-block-start-color: var(--edge-lit); }

/* --- Bare sets: the rule extends toward the text it belongs to ----------- */

.bare-set > li::before {
  transition: width var(--dur-mid) var(--ease-out),
              background var(--dur-mid) var(--ease-out);
}
.bare-set > li:hover::before {
  width: 4.5rem;
  background: linear-gradient(90deg, var(--edge-lit), transparent);
}

/* --- Wells settle very slightly when pointed at -------------------------- */

.well,
.insurers,
.hours-card,
.who__langs {
  transition: box-shadow var(--dur-mid) var(--ease-out);
}
.well:hover,
.insurers:hover,
.hours-card:hover,
.who__langs:hover {
  box-shadow: inset 0 1px 0 var(--edge-lit);
}

/* --- Insurer chips ------------------------------------------------------- */

.insurers__item {
  transition: border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}
.insurers__item:hover { border-color: var(--edge-lit); color: var(--ink); }

/* --- Step markers respond to their own step ------------------------------
 * Via transform ONLY. `da-ignite` already animates border-color and box-shadow
 * on the scroll timeline, and a running CSS animation outranks a plain hover
 * declaration — so a hover rule touching those two properties was simply dead
 * code. Scale is the one channel the animation leaves free.                 */

.steps__marker { transition: transform var(--dur-mid) var(--ease-out); }
.steps__item:hover .steps__marker { transform: scale(1.12); }

/* --- Everything above is motion, and motion is optional ------------------ */

@media (prefers-reduced-motion: reduce) {
  .plane > .face::after,
  .btn__arrow,
  .quote .stars,
  .quote__meta,
  .bare-set > li::before,
  .well, .insurers, .hours-card, .who__langs,
  .insurers__item,
  .steps__marker { transition: none; }

  .quote:hover .stars,
  .face--link:hover .btn__arrow,
  .steps__item:hover .steps__marker,
  a:hover .btn__arrow { transform: none; }
}
