/* Theme-only additions. The design system does not cover these — its launch
   pages have three flat nav items and no skip link. Kept out of the vendored
   files so re-vendoring stays a copy. */

.ws-skip { position: absolute; left: -9999px; top: 0; z-index: 100; padding: 10px 16px;
  background: var(--raised); color: var(--text-primary); border: 1px solid var(--border-strong);
  border-radius: var(--radius-md); font: 500 var(--size-body)/1 var(--font-text); }
.ws-skip:focus { left: 12px; top: 12px; }

/* .s-nav__in centres .s-nav__links, but the list itself has no align-items, so
   the text links stretch to the 36px control height and their text sits at the
   top of that box. */
.s-nav__links { align-items: center; }

/* The nav styles every descendant link with !important, which also hits the
   Contact button and leaves dark text on the dark action colour. */
.s-nav__links a.wsl-btn { color: var(--on-action) !important; }
.s-nav__links a.wsl-btn:hover { color: var(--on-action) !important; }

/* Body copy inside a section. The design system has no prose class — its pages
   set paragraphs inline per block. */
.ws-prose { max-width: 64ch; display: grid; gap: 16px; }
.ws-prose p { font: 400 var(--size-body)/var(--leading-body) var(--font-text); color: var(--text-secondary); }
.s-split .ws-prose { max-width: none; }

/* Mobile menu. The system hides the desktop nav below 860px and leaves the
   panel undesigned; this is the "simple glass sheet" the handoff asks for. */
.ws-mob { display: none; position: relative; }
.ws-mob > summary { list-style: none; cursor: pointer; display: grid; place-items: center;
  width: var(--control-h-sm); height: var(--control-h-sm); border-radius: var(--radius-md);
  border: 1px solid var(--border-strong); color: var(--text-primary); }
.ws-mob > summary::-webkit-details-marker { display: none; }
.ws-mob[open] > summary { background: color-mix(in oklch, var(--action) 10%, transparent); }
/* Opaque, not glass. The panel took .wsl-glass, which is 36% white over a
   backdrop-filter — and a filter that iOS declines to apply in this stacking
   context leaves the page legible straight through the menu.
   No scrim: .s-nav carries a backdrop-filter, which makes it the containing
   block for any fixed-position descendant, so a full-screen overlay from in
   here only ever covers the nav bar. The opaque surface and the raised shadow
   do the separating instead. */
.ws-mob__panel { position: absolute; right: 0; top: calc(100% + 10px); z-index: 60;
  display: grid; gap: 2px; min-width: min(268px, calc(100vw - 32px)); padding: 10px;
  background: var(--raised); border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-raised);
  max-height: calc(100vh - var(--control-h-sm) - 48px); overflow-y: auto;
  -webkit-backdrop-filter: none; backdrop-filter: none; }
.ws-mob__panel::before, .ws-mob__panel::after { display: none; }
.ws-mob__panel a { display: block; padding: 10px; border-radius: var(--radius-sm);
  font: 500 var(--size-body)/1 var(--font-text); color: var(--text-primary); }
.ws-mob__panel a.is-child { padding-left: 22px; color: var(--text-secondary); font-weight: 400; }
.ws-mob__panel a:hover { background: color-mix(in oklch, var(--action) 8%, transparent); }
.ws-mob__theme { margin-top: 6px; padding: 10px; border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong); background: none; color: var(--text-secondary);
  font: 500 var(--size-body)/1 var(--font-text); text-align: left; cursor: pointer; }

@media (max-width: 860px) { .ws-mob { display: block; } }

/* Tabs, driven by radios so they need no JavaScript. Arrow keys move between
   them because they are a radio group. The design system's tab bar is an
   underline, not a pill: .wsl-tabs supplies the gap and the bottom rule, and
   the active tab draws a 1.5px ::after. Overriding either broke the look, so
   this only supplies what a <label> cannot get from [aria-selected]. */
.ws-tabs > input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.ws-tabs__list { flex-wrap: wrap; }
.ws-tabs__list label { cursor: pointer; position: relative; }
.ws-tabs__panels > .ws-tabs__panel { display: none; }
.ws-tabs__panel { margin-top: var(--space-8); padding: var(--space-8); display: grid; gap: var(--space-4); justify-items: start; }
.ws-tabs__panel p { color: var(--text-secondary); max-width: 62ch; }

.ws-tabs > input:nth-of-type(1):checked ~ .ws-tabs__panels > .ws-tabs__panel:nth-child(1),
.ws-tabs > input:nth-of-type(2):checked ~ .ws-tabs__panels > .ws-tabs__panel:nth-child(2),
.ws-tabs > input:nth-of-type(3):checked ~ .ws-tabs__panels > .ws-tabs__panel:nth-child(3),
.ws-tabs > input:nth-of-type(4):checked ~ .ws-tabs__panels > .ws-tabs__panel:nth-child(4) { display: grid; }

/* Same treatment the system gives [aria-selected="true"]. */
.ws-tabs > input:nth-of-type(1):checked ~ .ws-tabs__list label:nth-child(1),
.ws-tabs > input:nth-of-type(2):checked ~ .ws-tabs__list label:nth-child(2),
.ws-tabs > input:nth-of-type(3):checked ~ .ws-tabs__list label:nth-child(3),
.ws-tabs > input:nth-of-type(4):checked ~ .ws-tabs__list label:nth-child(4) { color: var(--text-primary); }

.ws-tabs > input:nth-of-type(1):checked ~ .ws-tabs__list label:nth-child(1)::after,
.ws-tabs > input:nth-of-type(2):checked ~ .ws-tabs__list label:nth-child(2)::after,
.ws-tabs > input:nth-of-type(3):checked ~ .ws-tabs__list label:nth-child(3)::after,
.ws-tabs > input:nth-of-type(4):checked ~ .ws-tabs__list label:nth-child(4)::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 1.5px; background: var(--action); }

.ws-tabs > input:focus-visible ~ .ws-tabs__list label { outline: 2px solid var(--action); outline-offset: 2px; }

/* Section rhythm. The design system's own pages put one content block under a
   .s-head; this theme's sections can carry prose and items together, and with
   no rule between them the gap collapsed to nothing in some places and doubled
   in others. */
.s-sec .s-wrap > .ws-prose + * { margin-top: clamp(32px, 4vw, 56px); }
.s-sec .s-wrap > .s-head + .ws-prose { margin-top: 0; }
.s-caps { border-top: 1px solid var(--border); }

/* ── Lead form ────────────────────────────────────────────────────────────
   The fields themselves are the design system's .wsl-field / .wsl-control.
   What the system has no equivalent for is the page-level arrangement: the
   intro beside the fields, the two-column field grid, and the utility class
   Alpine toggles to swap the form for its success state. */

.ws-form__intro { display: grid; gap: 16px; align-content: start; }
.ws-form__closing { margin-top: 28px; padding-top: 20px; border-top: 1px solid var(--border); display: grid; gap: 8px; }
.ws-form__closingline { margin: 0; font: 500 16px/1.4 var(--font-text); color: var(--text-primary); }
.ws-form__closingbody { margin: 0; font: 400 14.5px/1.55 var(--font-text); color: var(--text-secondary); }

.ws-form__body { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
.ws-form__full { grid-column: 1 / -1; }
@media (max-width: 640px) { .ws-form__body { grid-template-columns: 1fr; } }

.ws-form__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; margin-top: 4px; }
.ws-form__error { margin: 0; font: 400 13px/1.45 var(--font-text); color: var(--critical); }

.ws-form__success { display: grid; gap: 10px; padding: 28px; border-radius: var(--radius-lg, 14px);
  background: var(--glass); border: 1px solid var(--border-strong); box-shadow: var(--glass-highlight); }
.ws-form__success p { margin: 0; font: 400 14.5px/1.55 var(--font-text); color: var(--text-secondary); }

.ws-form--muted { background: var(--raised); }

/* Alpine binds this on both the field wrapper and the success block; without a
   rule for it the success message showed permanently, above a live form. */
.ws-hidden { display: none !important; }

/* Honeypot. Off-screen rather than display:none, which some bots skip. */
.ws-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* The evidence table's heading is an h2 so the section keeps its place in the
   document outline. The vendored rule sets its type but not its box. */
.ev__title { margin: 0; }

/* Screen-reader-only text. Used for the "opens in a new tab" note on off-site
   links, and referenced by the templates generally. */
.ws-visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }

/* Evidence table repurposed with its own columns. The vendored rules set the
   fourth cell as a timestamp — mono and nowrap — which forces the table past
   its min-width and pushes the last column out of view when the cell holds a
   sentence. */
.ev--cols td.ts { font: inherit; white-space: normal; color: var(--text-secondary); }
.ev--cols td.src { white-space: nowrap; }

/* .ev paints its own opaque surface, which would sit on top of the glass. Let
   the wash through and take the rules down to the glass border so the table
   reads as the same component family as the cards beside it. */
.ev--cols { background: none; border: 0; border-radius: var(--r); }
.ev--cols .ev__head,
.ev--cols th,
.ev--cols td { border-bottom-color: var(--glass-border); }
.ev--cols .ev__head > div + div { border-left-color: var(--glass-border); }
.ev--cols tbody tr:last-child td { border-bottom: 0; }
.ev--cols .ev__scroll { border-radius: 0 0 var(--r) var(--r); }

/* A card in the design system opens with .s-card__img, which supplies the top
   of the box. These cards carry no media, so the body needs the top padding
   the image would otherwise have given it. */
.s-card > .s-card__b:first-child { padding-top: 24px; }

/* A row of tags inside a pillar or card. The stack has .stk__items for this;
   the card family had no equivalent. */
.s-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }

/* Embedded product interface. The kit is a desktop application layout with a
   fixed side nav, so below the design system's own breakpoint the frame is
   dropped and the link out carries it instead. */
.ws-embed { display: grid; gap: 16px; justify-items: start; }
.ws-embed__frame { width: 100%; aspect-ratio: 16 / 10; min-height: 520px; border: 0;
  border-radius: var(--radius-lg); background: var(--raised); box-shadow: var(--shadow-raised);
  display: block; color-scheme: light; }
.ws-embed__out { margin: 0; }
@media (max-width: 860px) { .ws-embed__frame { display: none; } }

/* A person's photo on a card. Circular, so it sits above the body rather than
   filling the media slot the way a preview graphic does. */
.ws-card__photo { display: block; width: 120px; height: 120px; border-radius: 50%;
  margin: 24px 24px 0; object-fit: cover; background: var(--ground); }
.s-card > .ws-card__photo + .s-card__b { padding-top: 18px; }

/* ── "A module inside yours" ───────────────────────────────────────────────
   The host is the firm's own product. The module carries the same surface and
   the same type as everything around it, marked only by a small label: the
   point of the picture is that it does not look like a visitor. */
/* Card and caption share the wrap's own column, so the graphic starts on the
   same left edge as every other section on the page rather than centring
   inside it. */
.ws-flow__in { max-width: 1040px; }
.ws-flow__host { border-radius: var(--radius-lg); overflow: hidden; }
.ws-flow__cap { margin: 28px 0 0; max-width: none; }

.ws-flow__bar { display: flex; align-items: center; gap: 22px; padding: 14px 20px;
  border-bottom: 1px solid var(--glass-border); }
.ws-flow__brand { font: 500 14px/1 var(--font-display); letter-spacing: -.02em; color: var(--text-primary); }
.ws-flow__brand::before { content: ""; display: inline-block; width: 14px; height: 14px; margin-right: 9px;
  border-radius: 4px; background: var(--text-muted); vertical-align: -2px; }
.ws-flow__nav { font: 400 12.5px/1 var(--font-text); color: var(--text-muted); }
.ws-flow__nav.is-on { color: var(--text-primary); }

.ws-flow__body { display: grid; grid-template-columns: minmax(0, 150px) minmax(0, 1fr); gap: 0; }
.ws-flow__side { display: grid; gap: 14px; align-content: start; padding: 22px 18px;
  border-right: 1px solid var(--glass-border); }
.ws-flow__side span { font: 400 12.5px/1 var(--font-text); color: var(--text-muted); }

.ws-flow__mod { padding: 22px 24px; display: grid; gap: 14px; align-content: start; }
.ws-flow__rows { display: grid; gap: 12px; }

@media (max-width: 720px) {
  .ws-flow__body { grid-template-columns: 1fr; }
  .ws-flow__side { flex-direction: row; grid-auto-flow: column; justify-content: start; gap: 18px;
    border-right: 0; border-bottom: 1px solid var(--glass-border); padding: 14px 18px; }
  .ws-flow__bar { gap: 14px; overflow-x: auto; }
}

/* Flow graphic entrance. .gfx's own reveal animates .gfx__doc, which this
   layout has none of, so the band arrived fully formed while the document fan
   beside it animated. The rows land one at a time, because them arriving in
   sequence is the claim the band is making. */
.ws-flow .ws-flow__host { transition: opacity .7s cubic-bezier(.2,.7,.2,1), translate .7s cubic-bezier(.2,.7,.2,1); }
.ws-flow:not(.is-in) .ws-flow__host { opacity: 0; translate: 0 18px; }
.ws-flow .ws-flow__rows .pv__row { transition: opacity .5s ease, translate .5s cubic-bezier(.2,.7,.2,1);
  transition-delay: calc(var(--i, 0) * 90ms + 300ms); }
.ws-flow:not(.is-in) .ws-flow__rows .pv__row { opacity: 0; translate: -10px 0; }

/* The sticky nav lifts off the page once you have left the top of it. */
.s-nav { transition: box-shadow .25s ease, border-color .25s ease; }
.s-nav.is-scrolled { box-shadow: var(--shadow-raised); border-bottom-color: var(--border-strong); }

@media (prefers-reduced-motion: reduce) {
  .ws-flow .ws-flow__host,
  .ws-flow .ws-flow__rows .pv__row { transition: none; opacity: 1; translate: none; }
  .s-nav { transition: none; }
}
