/* extras.css */

/* ══════════════════════════════════════════════════════════════
   BL CONTROL PANEL — the design knobs. Edit values HERE; every
   rule below consumes them. Load-bearing geometry (cap-cover law,
   bead travel) is DERIVED from these via calc(), so changing a
   knob cannot break an invariant. After editing: hard-refresh
   (Ctrl+F5) — the stylesheet is version-cached.
   ══════════════════════════════════════════════════════════════ */
:root {
  --bl-masthead-scale: clamp(2.3rem, 1.2rem + 5.5vw, 4.75rem); /* whole lockup: mark + words + toggle */
  --bl-mark-size:      1.8em;    /* logo; rides the lockup scale        */
  --bl-dash-width:     0.85em;   /* toggle track length                 */
  --bl-dash-height:    0.13em;   /* track thickness                     */
  --bl-bead-size:      0.42em;   /* toggle bead diameter                */
  --bl-bead-overhang:  0.05em;   /* bead caps past the track end;
                                    cap-cover law: keep >= 0.01em       */
  --bl-lockup-air:     var(--wp--preset--spacing--30); /* interior H1 -> first section */
  --bl-panel-light:    #FFFFFF;  /* card + field fill on fog            */
  --bl-panel-dark:     #16233A;  /* card + field fill on ink            */
  --bl-seam-width:     2px;      /* seam divider thickness              */
  --bl-contour-alpha:  0.06;     /* reserved: contour texture layer     */
  /* Center band (pass 5) */
  --bl-band-width:     1201px;   /* center band; > wideSize (1200px) so wide
                                    blocks always sit on the band. Rails only
                                    exist when viewport > this → desktop-only
                                    by construction, no media query          */
  --bl-band-edge-w:    1px;      /* hairline sharpness; 0 removes the edge  */
  --bl-band-edge:      var(--wp--preset--color--rule); /* flips with mode   */
  --bl-rail-fill:      #E7ECF3;  /* light rails: fog tinted toward slate;
                                    dark override lives in pass 5 below     */
}

/* THE SEAM — the one signature element.
   Every section join is a visible, honored brass hairline, not a flat break.
   Rationale (build with intent, not as decoration): nothing hidden — the joins
   are where the value is; and it's literally true to the subject's math
   (a manifold is charts joined along seams). */
.wp-block-separator.is-style-seam {
  border: 0;
  height: var(--bl-seam-width);
  max-width: var(--wp--style--global--wide-size);
  margin-inline: auto;
  background: linear-gradient(90deg,
    transparent 0%,
    var(--wp--preset--color--seam) 15%,
    var(--wp--preset--color--seam) 85%,
    transparent 100%);
  opacity: 0.9;
}

/* Optional enhancement (nice-to-have, not required): a subtle fold at center.
   Keep it restrained. */
.wp-block-separator.is-style-seam::after {
  content: "";
  display: block;
  width: 10px; height: 10px;
  margin: -5px auto 0;
  background: var(--wp--preset--color--seam);
  transform: rotate(45deg);
  opacity: 0.6;
}

/* Quality floor */
/* Inline-SVG link :visited paint guard. Chrome repaints the fill of visited
   SVG <a> elements; descendants that inherit fill flicker dark depending on
   the viewer's browsing history, and DevTools hides it (visited-link privacy
   reports the unvisited value) — verify with screenshots. fill/stroke are on
   the small whitelist of properties :visited rules may set. */
svg a:visited { fill: inherit; stroke: inherit; }
.skip-link { position:absolute; left:-9999px; }
.skip-link:focus { left:1rem; top:1rem; position:fixed; z-index:99; background:var(--wp--preset--color--ground); color:var(--wp--preset--color--paper); padding:.5rem 1rem; }
:where(a,button,input,select,textarea):focus-visible { outline:2px solid var(--wp--preset--color--seam); outline-offset:2px; }
@media (prefers-reduced-motion: reduce) { *,*::before,*::after { animation:none!important; transition:none!important; scroll-behavior:auto!important; } }

/* ============================================================
   BASIN LABS SKIN — light default, dark via [data-theme="dark"]
   The whole flip is CSS-custom-property re-pointing: core's
   preset classes resolve var(--wp--preset--color--*) per
   element, so redefining the vars under the dark scope restyles
   every block without touching serialized markup.
   Contrast (WCAG AA, computed at token time):
     light — ground on paper 13.3 · dim 5.6 · seam 5.3
     dark  — ground on paper 16.0 · dim 6.2 · seam 11.7
     panel — paper 13.3 · dim 6.5 · seam 9.7
   ============================================================ */

:root { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

:root[data-theme="dark"],
:root[data-theme="dark"] body {
  --wp--preset--color--ground: #E6EDF3; /* text on dark page */
  --wp--preset--color--paper:  #0D1117; /* page background */
  --wp--preset--color--seam:   #F5C542; /* lambda gold earns AA on dark */
  --wp--preset--color--rule:   #30363D;
  --wp--preset--color--dim:    #8B949E;
}

/* Panels: blocks that declare ground as BACKGROUND (footer, banner,
   pov, service-detail, buttons) stay navy panels in dark mode, and
   their inner paper/dim/seam text stays legible — scoped re-pointing,
   no markup changes. Panels sit 1.2:1 against the dark page, so the
   rule hairline supplies the boundary. */
:root[data-theme="dark"] .has-ground-background-color {
  --wp--preset--color--ground: #16233A; /* elevated basin navy */
  --wp--preset--color--paper:  #E6EDF3;
  --wp--preset--color--dim:    #9BA7BC;
  --wp--preset--color--seam:   #F5C542;
  border: 1px solid var(--wp--preset--color--rule);
}

body { transition: background-color .3s ease, color .3s ease; }

/* FluentForm submit speaks the same button language as core buttons
   (its stock blue is off-token). Dark mode gives it the panel treatment. */
.fluentform .ff-btn-submit {
  background-color: var(--wp--preset--color--ground) !important;
  border-color: var(--wp--preset--color--ground) !important;
  color: var(--wp--preset--color--paper) !important;
}
/* Dark mode: the submit is the ONE action in the section — it gets the
   interactive gold the toggle thumb already established, not the panel
   camouflage that made it near-invisible (cold-lens find F4, Round 2).
   #152A4E on #F5C542 = 8.8:1. */
:root[data-theme="dark"] .fluentform .ff-btn-submit {
  background-color: #F5C542 !important;
  border-color: #F5C542 !important;
  color: #152A4E !important;
}

/* --- Brand masthead: mark + Basin [dash-toggle] Labs ----------- */
/* Identity-scale: the lockup IS the header. Everything inside is
   em-sized, so mark, words, and dash-toggle scale as one unit. */
.bl-brand {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.18em;
  font-family: var(--wp--preset--font-family--display);
  /* control-panel knob; slope tuned so the lockup never exceeds the
     content column on a 320px screen */
  font-size: var(--bl-masthead-scale);
  font-weight: 800;
  line-height: 1;
}
.bl-brand__home {
  display: flex;
  align-items: center;
  gap: 0.28em;
  text-decoration: none;
  color: var(--wp--preset--color--ground);
}
.bl-brand__home:hover .bl-brand__word {
  text-decoration: underline;
  text-decoration-color: var(--wp--preset--color--seam);
  text-decoration-thickness: 0.05em;
  text-underline-offset: 0.14em;
}
.bl-mark { width: var(--bl-mark-size); height: var(--bl-mark-size); display: block; }
/* The mark's near-black outline dissolves on the dark page (1.06:1);
   a faint light rim keeps the basin silhouette crisp. */
:root[data-theme="dark"] .bl-mark { filter: drop-shadow(0 0 1px rgba(230, 237, 243, 0.4)); }

/* --- The dash-toggle: an em-dash that is also the theme switch ---
   Typography first, control second: true em-dash proportions in the
   text color, with a small gold bead resting on the line. The dash
   itself warms to gold on hover/focus — that is the invitation. */
.bl-dash-toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  width: var(--bl-dash-width);
  height: 1em;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  font: inherit;
}
.bl-dash-toggle__track {
  position: absolute;
  left: 0; right: 0;
  top: 50%;
  height: var(--bl-dash-height);
  margin-top: calc(var(--bl-dash-height) / -2);
  border-radius: calc(var(--bl-dash-height) / 2);
  background: var(--wp--preset--color--ground);
  transition: background-color .25s ease;
}
.bl-dash-toggle:hover .bl-dash-toggle__track,
.bl-dash-toggle:focus-visible .bl-dash-toggle__track {
  background: var(--wp--preset--color--seam);
}
.bl-dash-toggle__thumb {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--bl-bead-size);
  height: var(--bl-bead-size);
  border-radius: 50%;
  box-sizing: border-box;
  background: #F5C542;               /* lambda gold, both modes */
  border: 0.03em solid #152A4E;      /* hairline navy rim */
  color: #152A4E;                    /* icon: 8.8:1 on gold */
  transition: transform .25s cubic-bezier(.4, 0, .2, 1);
  /* Cap-cover law: the bead is a circle, so its silhouette tapers to
     zero at the edges while the track (with rounded end-caps) stays
     full-height everywhere. Flush or inset positions leave the cap
     peeking around the bead's taper (reads as a nub). The bead must
     OVERHANG the track end (>= 0.01em) to swallow the cap — the line
     ends INTO the bead. Travel is DERIVED from the knobs, so resizing
     the dash or bead can no longer break this. */
  transform: translateX(calc(-1 * var(--bl-bead-overhang)));
}
.bl-dash-toggle:hover .bl-dash-toggle__thumb,
.bl-dash-toggle:focus-visible .bl-dash-toggle__thumb { transform: translateX(calc(-1 * var(--bl-bead-overhang))) scale(1.25); }
:root[data-theme="dark"] .bl-dash-toggle .bl-dash-toggle__thumb { transform: translateX(calc(var(--bl-dash-width) - var(--bl-bead-size) + var(--bl-bead-overhang))); }
:root[data-theme="dark"] .bl-dash-toggle:hover .bl-dash-toggle__thumb,
:root[data-theme="dark"] .bl-dash-toggle:focus-visible .bl-dash-toggle__thumb { transform: translateX(calc(var(--bl-dash-width) - var(--bl-bead-size) + var(--bl-bead-overhang))) scale(1.25); }
.bl-icon { position: absolute; width: 70%; height: 70%; transition: opacity .2s ease, transform .3s ease; }
.bl-icon--sun  { opacity: 0; transform: rotate(-90deg) scale(0.5); }
.bl-icon--moon { opacity: 1; transform: rotate(0) scale(1); }
:root[data-theme="dark"] .bl-icon--sun  { opacity: 1; transform: rotate(0) scale(1); }
:root[data-theme="dark"] .bl-icon--moon { opacity: 0; transform: rotate(90deg) scale(0.5); }

/* ============================================================
   AESTHETIC PASSES 2026-07-12 (attack-round rerank, AESTHETIC-
   NOTES.md Round 2). Mass before lines: fills first, then rhythm.
   ============================================================ */

/* --- Panel tier (pass 4). Cards (rule-bordered groups) sit one
   plane above the page in BOTH modes — light finally gets the
   #FFF-on-#F7F7F8 lift that dark already had via ground panels.
   Depth is fill + the existing hairline; no shadows, no radius.
   Contrast (C6, computed): light ground-on-#FFF 14.9 · dim 6.1 ·
   seam 5.6; dark panel values match the header table (dim bumped
   to #9BA7BC exactly as the ground-panel rule does). */
.wp-block-group.has-rule-border-color {
  background-color: var(--bl-panel-light);
}
:root[data-theme="dark"] .wp-block-group.has-rule-border-color {
  background-color: var(--bl-panel-dark);
  --wp--preset--color--dim: #9BA7BC;
}

/* --- Interior title lockup (pass 3). On interior pages the post
   title and the first content section read as ONE unit: the
   section's hero-scale top padding (spacing-60) collapsed to
   spacing-30, killing the ~10.5rem dead zone (main padding-50 +
   section padding-60) measured on every interior page. Inline
   padding is C1-serialized in content, hence the !important.
   Home keeps its hero air (body.home excluded). */
body.page:not(.home) .wp-block-post-content > .wp-block-group.alignfull:first-child {
  padding-top: var(--bl-lockup-air) !important;
}

/* --- Form pass (pass 2, CSS layer). FluentForm chrome onto tokens:
   fields are panels (same tier as cards), labels speak the site's
   label grammar (mono sm dim), required-marks are seam not stock
   red, focus is the seam ring (line, not glow). Submit label text
   and the phone field are form-config, not CSS — handled DB-side. */
.fluentform .ff-el-form-control {
  background-color: var(--bl-panel-light);
  border: 1px solid var(--wp--preset--color--rule);
  border-radius: 2px;
  color: var(--wp--preset--color--ground);
}
.fluentform .ff-el-form-control::placeholder {
  color: var(--wp--preset--color--dim);
  opacity: 1;
}
:root[data-theme="dark"] .fluentform .ff-el-form-control {
  background-color: var(--bl-panel-dark);
  border-color: #30363D;
  color: #E6EDF3;
}
:root[data-theme="dark"] .fluentform .ff-el-form-control::placeholder { color: #8B949E; }
.fluentform .ff-el-form-control:focus {
  border-color: var(--wp--preset--color--seam);
  box-shadow: none;
  outline: 2px solid var(--wp--preset--color--seam);
  outline-offset: 1px;
}
.fluentform .ff-el-input--label label {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--sm);
  font-weight: 400;
  color: var(--wp--preset--color--dim);
}
.fluentform .ff-el-input--label.ff-el-is-required.asterisk-right label:after,
.fluentform .ff-el-input--label.ff-el-is-required.asterisk-left label:before {
  color: var(--wp--preset--color--seam);
}
.fluentform .ff-btn-submit {
  border-radius: 999px;
  padding: 0.7em 1.8em;
  font-family: var(--wp--preset--font-family--body);
  font-weight: 600;
}

/* --- Center band (pass 5, 2026-07-23). The page becomes a sheet on
   a desk: tinted rails left/right, hard-edged band down the middle
   framing the content column. Gardener's ask: draw the desktop eye
   inward; "sharper" band → hard gradient stops + rule hairline (the
   established boundary grammar), NOT a soft fade.
   Mechanics: one layered gradient on body; the CENTER STOPS ARE
   TRANSPARENT so body's own background-color remains the band —
   every computed contrast ratio above survives unchanged, cards
   keep their #FFF-on-fog lift, and the .3s mode-fade still paints
   the majority surface (rails snap on toggle; minor area, accepted).
   Rails are non-text surfaces: no AA obligation. Phones never see
   rails (band-width > any phone viewport). */
/* --- Pass 5 amendment (2026-07-23, gardener's catch): ONE TEMPO for the
   theme flip. background-image gradients cannot transition — the rails
   snapped while the band's center (body background-color) faded over .3s,
   and on a wide viewport the mismatch read as a glitch. (⊘ correction, same
   night: two @property attempts were judged failures by a corrupted probe —
   browser-extension isolation was shadowing test writes; the "Chromium
   inheritance freeze" claim is UNPROVEN and retracted. The @property route
   may work; nobody should re-litigate it — the structure below is sturdier
   anyway.) Final structure, boring and universal: TWO fixed rail layers,
   one light and one dark, crossfaded by OPACITY — which animates
   everywhere — locked to the same .3s ease as the center. body paints no
   gradient anymore; the layers sit at z-index -1 behind content; the band
   center remains body's background-color exactly as before, so every
   contrast ratio and the cards' lift survive unchanged. Geometry knobs
   (--bl-band-width, --bl-band-edge-w) still steer both layers; per-mode
   rail/edge colors are now literals inside each layer below. */
body::before,
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  transition: opacity .3s ease;
}
body::before { /* light rails: fog toward slate, rule-slate hairlines */
  opacity: 1;
  background-image: linear-gradient(90deg,
    #E7ECF3 0,
    #E7ECF3 calc(50% - var(--bl-band-width) / 2 - var(--bl-band-edge-w)),
    #33415C calc(50% - var(--bl-band-width) / 2 - var(--bl-band-edge-w)),
    #33415C calc(50% - var(--bl-band-width) / 2),
    transparent calc(50% - var(--bl-band-width) / 2),
    transparent calc(50% + var(--bl-band-width) / 2),
    #33415C calc(50% + var(--bl-band-width) / 2),
    #33415C calc(50% + var(--bl-band-width) / 2 + var(--bl-band-edge-w)),
    #E7ECF3 calc(50% + var(--bl-band-width) / 2 + var(--bl-band-edge-w))
  );
}
body::after { /* dark rails: deeper ink than the #0D1117 page, so the band
   reads as the lifted surface — dark mode's "white band". */
  opacity: 0;
  background-image: linear-gradient(90deg,
    #070B12 0,
    #070B12 calc(50% - var(--bl-band-width) / 2 - var(--bl-band-edge-w)),
    #30363D calc(50% - var(--bl-band-width) / 2 - var(--bl-band-edge-w)),
    #30363D calc(50% - var(--bl-band-width) / 2),
    transparent calc(50% - var(--bl-band-width) / 2),
    transparent calc(50% + var(--bl-band-width) / 2),
    #30363D calc(50% + var(--bl-band-width) / 2),
    #30363D calc(50% + var(--bl-band-width) / 2 + var(--bl-band-edge-w)),
    #070B12 calc(50% + var(--bl-band-width) / 2 + var(--bl-band-edge-w))
  );
}
:root[data-theme="dark"] body::before { opacity: 0; }
:root[data-theme="dark"] body::after  { opacity: 1; }
/* Cards previously snapped on the flip; they join the same tempo. */
.wp-block-group.has-rule-border-color { transition: background-color .3s ease, border-color .3s ease; }

/* --- Card title seam (pass 6, 2026-07-24, gardener's refinement): the
   mono kicker labels inside cards were redundant with their titles and
   are removed from content; the title itself now carries a hairline
   underneath — same rule-color grammar as the card border, flips with
   the theme via the preset. Section-level kickers (outside cards) are
   untouched and remain part of the page grammar. */
.wp-block-group.has-rule-border-color :is(h2, h3) {
  border-bottom: 1px solid var(--wp--preset--color--rule);
  padding-bottom: 0.5em;
}
/* Full-bleed navy sections (banner/footer) intentionally bleed OVER
   the rails — the band breaks where the design already goes full-width.
   If the gardener wants those banded too: that's a markup pass, not CSS. */
