/* Open Shore - "Horizon" corporate identity.
   Cool sibling to Uki: ink + deep-water accent (Uki keeps the amber).
   Restraint is the premium signal. Whitespace is the hero. One motion:
   the horizon hairline draws in once on load. Committed light "paper"
   aesthetic - the warm paper is the shared family DNA.
   ONE typeface, self-hosted (variable weight axis) - no external origin, which
   is what lets the CSP stay a strict 'self'. The 2025 refont moved the whole
   site to a single grotesque; see the --sans note below. */

/* Hanken Grotesk: a modern grotesque with subtly softened corners, chosen as an
   open, self-hostable analog to the character of Amazon's 2025 "Ember Modern"
   marketing typeface (Ember Modern is proprietary, so this matches its feel
   rather than the font itself). Variable weight axis, latin subset. Carries the
   whole site: display and body alike. */
@font-face {
  font-family: "Hanken Grotesk";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/fonts/hanken-grotesk-standard.woff2") format("woff2");
}

:root {
  --paper: #f6f4ef; /* a hair cooler/lighter than Uki's Snow */
  --ink: #1c2a33; /* deep slate-ink, not pure black */
  --ink-soft: #55636b; /* secondary text */
  --ink-faint: #646e74; /* meta / labels - darkened to clear WCAG AA (~4.7:1 on
    paper); still lighter than --ink-soft, so the faint/soft/ink hierarchy holds */
  --water: #2f5a66; /* the single accent, used sparingly */
  --water-deep: #24454f;
  --hairline: #d9d4c9; /* dividers on paper */

  --measure: 42rem; /* ~672px single column */
  --step: 8px; /* baseline grid */

  --sans: "Hanken Grotesk", system-ui, -apple-system, "Segoe UI", Helvetica,
    Arial, sans-serif;
  /* --serif is retained as an alias so the many var(--serif) display usages keep
     working after the 2025 refont, which moved display and body to the same
     grotesque. Point it back at a display face here to reintroduce a two-family
     system. */
  --serif: var(--sans);

  color-scheme: light;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  font-optical-sizing: auto; /* let Fraunces/Inter bloom at display sizes */
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.65;
  font-weight: 400;
}

a {
  color: var(--water);
  text-decoration: none;
  background-image: linear-gradient(var(--water), var(--water));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 1px;
  transition: background-size 220ms ease;
  padding-bottom: 1px;
}
a:hover,
a:focus-visible {
  background-size: 100% 1px;
}
a:focus-visible {
  outline: 2px solid var(--water);
  outline-offset: 3px;
  border-radius: 2px;
}

/* Skip link: off-screen until focused, then snaps in as the first stop so a
   keyboard user can jump past the brand + six tabs straight to the content. */
.skip-link {
  position: absolute;
  left: 12px;
  top: -60px;
  z-index: 100;
  padding: 10px 16px;
  border-radius: 8px;
  background: var(--ink);
  background-image: none;
  color: var(--paper);
  font-family: var(--sans);
  font-size: 0.9rem;
  font-weight: 500;
  transition: top 160ms ease;
}
.skip-link:focus {
  top: 12px;
}
.skip-link:focus-visible {
  outline: 2px solid var(--water);
  outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
  .skip-link {
    transition: none;
  }
}

/* ---- Layout ---------------------------------------------------------- */

.page {
  max-width: var(--measure);
  margin: 0 auto;
  padding: clamp(28px, 6vw, 56px) 24px clamp(48px, 8vw, 88px);
}

.block {
  margin-top: clamp(48px, 9vw, 96px);
}
/* When a block opens the page (no masthead above it, e.g. home), its
   margin-top would stack on top of .page's own top padding. */
.page > .block:first-child {
  margin-top: 0;
}

/* ---- Site nav (tabs) ------------------------------------------------- */

.sitenav {
  max-width: var(--measure);
  margin: 0 auto;
  padding: clamp(20px, 5vw, 36px) 24px 0;
}

/* Brand lockup: the Open Shore mark (horizon + wave) plus wordmark, on every
   page, linking home. Sits above the tab row so it never competes with the
   five tabs for width on a phone. */
.brand {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin-bottom: clamp(16px, 3.5vw, 24px);
  text-decoration: none;
  background-image: none;
  color: var(--ink);
}
.brand-mark {
  display: block;
  flex: none;
  width: 42px;
  height: 42px;
}
.brand-word {
  font-family: var(--serif);
  font-weight: 500;
  font-size: 1.4rem;
  letter-spacing: 0.02em;
  color: var(--ink);
}
.brand:hover .brand-word,
.brand:focus-visible .brand-word {
  color: var(--water-deep);
}
.sitenav-tabs {
  display: flex;
  gap: clamp(18px, 5vw, 40px);
  list-style: none;
  margin: 0;
  padding: 0;
  border-bottom: 1px solid var(--hairline);
  /* Five tabs no longer fit one narrow-phone row. Keep them on a single line
     (the active underline sits on this border) and let the strip scroll
     horizontally instead of shrinking/wrapping the labels. Scrollbar hidden;
     the row is short and thumb-swipeable. */
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none; /* Firefox */
  -webkit-overflow-scrolling: touch;
}
.sitenav-tabs::-webkit-scrollbar {
  display: none; /* WebKit/Blink */
}
.sitenav-tabs > li {
  flex: 0 0 auto; /* never shrink a tab, so labels + WIP badge stay on one line */
}
.sitenav-tab {
  display: inline-block;
  white-space: nowrap;
  font-family: var(--sans);
  font-size: 0.9rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--ink-faint);
  padding: 2px 0 12px;
  margin-bottom: -1px;
  border-bottom: 2px solid transparent;
  background-image: none;
  transition:
    color 200ms ease,
    border-color 200ms ease;
}
.sitenav-tab:hover,
.sitenav-tab:focus-visible {
  color: var(--ink);
  background-image: none;
}
.sitenav-tab.is-active {
  color: var(--ink);
  border-bottom-color: var(--water);
}
.sitenav-ext {
  font-size: 0.85em;
  color: var(--ink-faint);
}

/* WIP badge on in-development tabs (Marketing, Media). Small, quiet, uppercase
   pill so the tab reads as navigable-but-unfinished rather than broken. */
.sitenav-wip {
  display: inline-block;
  margin-left: 5px;
  padding: 1px 5px;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  font-size: 0.58rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  vertical-align: 1px;
}

/* On phones the five labels (~294px of text) plus the roomy desktop gaps
   overrun the row. Spread the tabs edge to edge with space-between, trim the
   gutters, and let the font ease down so every label stays visible without any
   horizontal scroll, down to a 320px viewport. The overflow-x fallback above
   only ever engages under large accessibility text zoom. */
@media (max-width: 480px) {
  .sitenav {
    padding-left: 20px;
    padding-right: 20px;
  }
  /* Match the page column's left edge to the nav's (both 20px) so the header
     and body don't sit on a 4px stagger at the very top of the page. */
  .page {
    padding-left: 20px;
    padding-right: 20px;
  }
  .sitenav-tabs {
    gap: 6px;
    justify-content: space-between;
  }
  .sitenav-tab {
    font-size: clamp(0.72rem, 3.4vw, 0.9rem);
    letter-spacing: 0;
    /* Grow the vertical hit area toward a ~44px thumb target without touching
       label width or the single-row 320px fit (vertical space is free). */
    padding-top: 9px;
    padding-bottom: 14px;
  }
}

/* ---- Masthead -------------------------------------------------------- */

.masthead {
  padding-bottom: calc(var(--step) * 1);
}

.wordmark {
  font-family: var(--serif);
  font-weight: 500;
  font-size: 1.05rem;
  letter-spacing: 0.02em;
  margin: 0 0 clamp(28px, 6vw, 56px);
  color: var(--ink);
}

.identity {
  font-family: var(--serif);
  font-weight: 420;
  font-size: clamp(1.5rem, 4.5vw, 2.35rem);
  line-height: 1.15;
  letter-spacing: -0.014em;
  font-optical-sizing: auto;
  margin: 0;
  max-width: 20ch;
  color: var(--ink);
  text-wrap: balance;
}
.identity-coda {
  color: var(--ink-soft);
}
/* Byline treatment: the coda drops to its own line under the headline at deck
   scale rather than flowing inline at H1 size. Used on the heroes whose coda
   is a full supporting line (home, marketing). */
.identity-byline {
  display: block;
  margin-top: clamp(14px, 2.5vw, 22px);
  font-size: clamp(1.15rem, 3vw, 1.5rem);
  line-height: 1.4;
  letter-spacing: 0;
  max-width: 40ch;
  text-wrap: pretty;
}

/* The one gesture: horizon hairline draws in on load. The line dissolves
   at both margins (gradient) so the shoreline fades rather than hard-stops. */
.horizon {
  height: 1px;
  background: linear-gradient(
    90deg,
    transparent 0%,
    var(--ink) 10%,
    var(--ink) 90%,
    transparent 100%
  );
  margin-top: clamp(32px, 7vw, 64px);
  transform: scaleX(0);
  transform-origin: left center;
  animation: draw-horizon 620ms cubic-bezier(0.22, 1, 0.36, 1) 120ms forwards;
}

@keyframes draw-horizon {
  to {
    transform: scaleX(1);
  }
}

/* ---- Type helpers ---------------------------------------------------- */

.eyebrow {
  font-family: var(--sans);
  font-weight: 500;
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 0 calc(var(--step) * 2);
}

.lede {
  font-family: var(--serif);
  font-size: clamp(1.15rem, 2.6vw, 1.4rem);
  line-height: 1.5;
  color: var(--ink);
  margin: 0;
  max-width: 34ch;
  text-wrap: pretty;
}

/* ---- Registry (portfolio) ------------------------------------------- */

.registry {
  list-style: none;
  margin: 0;
  padding: 0;
}

.registry-row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px 32px;
  justify-content: space-between;
  align-items: baseline;
  padding: calc(var(--step) * 3) clamp(4px, 2vw, 20px);
  margin: 0 clamp(-4px, -2vw, -20px);
  border-top: 1px solid var(--hairline);
  border-radius: 6px;
  transition:
    background-color 220ms ease,
    box-shadow 220ms ease;
}
.registry-row:hover {
  background-color: rgba(47, 90, 102, 0.04); /* whisper of deep-water */
}
.registry-row:last-child {
  border-bottom: 1px solid var(--hairline);
}

.registry-main {
  flex: 1 1 20rem;
  min-width: 0;
}

.registry-name {
  font-family: var(--serif);
  font-size: 1.4rem;
  font-weight: 500;
  margin: 0 0 calc(var(--step) * 1);
  color: var(--ink);
  text-wrap: pretty; /* avoid single-word orphans when a name + descriptor wraps */
}
.registry-descriptor {
  color: var(--ink-faint);
  font-weight: 400;
  font-size: 1.1rem;
  /* Wrap the descriptor as a whole unit (dropping to its own line) rather than
     fracturing mid-phrase and orphaning a trailing word. */
  white-space: nowrap;
}

.registry-blurb {
  margin: 0;
  color: var(--ink-soft);
  max-width: 46ch;
  font-size: 0.98rem;
}

.registry-meta {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-shrink: 0;
  font-size: 0.85rem;
}

.status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-weight: 500;
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--water-deep);
}
.status::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--water);
}
.status--in-development,
.status--coming-soon {
  color: var(--ink-faint);
}
.status--in-development::before,
.status--coming-soon::before {
  background: var(--ink-faint);
}

.registry-year {
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

/* Products page: a product spotlight's status + year, set under the lede. */
.product .lede {
  margin-top: calc(var(--step) * 2);
}
.product-meta {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-top: calc(var(--step) * 2);
  font-size: 0.85rem;
}

/* WIP pages (Marketing, Media): status pill sits just under the eyebrow. */
.wip-status {
  margin: 0 0 calc(var(--step) * 3);
}

/* OS Marketing: the honest "new practice" note under the offer card. */
.founding-note {
  margin-top: calc(var(--step) * 3);
  color: var(--ink-soft);
  font-size: 0.95rem;
  max-width: 60ch;
}

/* A whole registry row that acts as a link (portfolio → product site). */
.registry-row--link {
  position: relative;
}
.registry-cover {
  position: absolute;
  inset: 0;
  z-index: 1;
  background-image: none;
  border-radius: 6px;
}
.registry-link {
  color: var(--water-deep);
  font-weight: 500;
  white-space: nowrap;
  background-image: none;
  transition: color 200ms ease;
}
.registry-row--link:hover .registry-link {
  color: var(--water);
}

/* Lean "Ventures" index on the home page: one quiet row each, name + short
   descriptor + a link, no blurb. Drop the name's bottom margin (there's no
   blurb beneath it) so each row reads as a single, tidy line. */
.registry-row--index .registry-name {
  margin-bottom: 0;
}

/* Inline call-to-action link under a block's lede. */
.block-cta {
  display: inline-block;
  margin-top: calc(var(--step) * 2);
  font-family: var(--sans);
  font-weight: 500;
  font-size: 0.95rem;
  color: var(--water-deep);
  background-image: none;
}
.block-cta:hover,
.block-cta:focus-visible {
  color: var(--water);
  background-image: none;
}
.block-cta span {
  display: inline-block;
  transition: transform 200ms ease;
}
.block-cta:hover span,
.block-cta:focus-visible span {
  transform: translateX(3px);
}

/* ---- Owner / operator card ------------------------------------------ */
/* A business-card block: the person behind Open Shore, stated plainly. A
   legitimacy signal (owner-operated) as much as an introduction. Uses the
   card vocabulary already in the system (.track: hairline border, radius,
   whisper of deep-water, hover lift) plus the water-accent monogram. */

.ownercard {
  display: flex;
  align-items: center;
  gap: clamp(18px, 4vw, 30px);
  margin: 0;
  padding: clamp(22px, 3.5vw, 34px);
  border: 1px solid var(--hairline);
  border-radius: 14px;
  background: rgba(47, 90, 102, 0.03);
  transition:
    border-color 240ms ease,
    transform 240ms ease,
    box-shadow 240ms ease;
}
.ownercard:hover {
  border-color: var(--water);
  transform: translateY(-2px);
  /* Layered shadow: a tight contact shadow under a soft ambient one, so the
     lift reads as depth rather than a single flat drop. */
  box-shadow:
    0 1px 2px rgba(28, 42, 51, 0.05),
    0 12px 34px rgba(28, 42, 51, 0.09);
}
/* Pressed state: the card settles under the finger, matching the tactile
   scale used on .door and the consult FAB. */
.ownercard:active {
  transform: translateY(0) scale(0.997);
}

.ownercard-monogram {
  flex: none;
  align-self: flex-start;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--serif);
  font-weight: 500;
  font-size: 1.55rem;
  letter-spacing: 0.02em;
  color: var(--water-deep);
  background: rgba(47, 90, 102, 0.08);
  border: 1px solid var(--hairline);
  /* Letterpress depth: a faint top highlight over a soft inner shade so the
     JB disc sits into the paper rather than floating flat on it. */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.55),
    inset 0 -1px 3px rgba(28, 42, 51, 0.05);
}

.ownercard-body {
  min-width: 0;
  margin: 0;
}
.ownercard-name {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(1.4rem, 3.4vw, 1.7rem);
  line-height: 1.12;
  color: var(--ink);
  margin: 0;
}
.ownercard-role {
  font-family: var(--sans);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--water-deep);
  margin: calc(var(--step) * 1.25) 0 0;
}
.ownercard-note {
  color: var(--ink-soft);
  font-size: 0.95rem;
  line-height: 1.55;
  max-width: 46ch;
  margin: calc(var(--step) * 2) 0 0;
}
.ownercard-links {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 12px;
  margin: calc(var(--step) * 2) 0 0;
  font-size: 0.92rem;
}
.ownercard-sep {
  color: var(--ink-faint);
}
@media (max-width: 34rem) {
  .ownercard {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* ---- Contact + entity ----------------------------------------------- */

.contact {
  margin: 0;
}
/* Give the contact details air below a closing statement (home, consulting,
   marketing all end on a .lede--close immediately above the contact block). */
.lede--close + .contact {
  margin-top: calc(var(--step) * 3);
}
/* Web page: the contact details sit under a block-cta, so they need a little
   air above them (the CTA is an inline-block on the preceding line). */
.contact--web {
  margin-top: calc(var(--step) * 4);
}
.contact-line {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  margin: 0 0 calc(var(--step) * 1.5);
  align-items: baseline;
}
.contact-label {
  flex: 0 0 12rem;
  color: var(--ink-soft);
  font-size: 0.95rem;
}

.entity {
  font-style: normal;
  margin-top: calc(var(--step) * 4);
  padding-top: calc(var(--step) * 3);
  border-top: 1px solid var(--hairline);
  color: var(--ink-soft);
  font-size: 0.95rem;
  line-height: 1.7;
}

/* ---- Prose ---------------------------------------------------------- */

.prose {
  margin: 0;
  max-width: 62ch;
  color: var(--ink-soft);
  font-size: 1.02rem;
  text-wrap: pretty;
}
.lede--advisory,
.lede--close {
  max-width: 46ch;
}

/* ---- Wordmark section label (OS Consulting, Products, …) ------------- */
/* Interior pages label their section here; the brand + home link now live in
   the site header, so this is just the quiet unit name above the headline. */
.wordmark-unit {
  color: var(--ink-soft);
}

/* ---- Intro: headshot + lede ----------------------------------------- */

.intro-grid {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: clamp(22px, 4vw, 40px);
  align-items: start;
}
.intro-grid .lede {
  max-width: 52ch;
}
/* Home "Background" bio: the paragraph is set as .prose (sans, ink-soft) so it
   reads as connected narrative under the hero rather than a second display-scale
   block. Center the monogram against the shorter paragraph so the column isn't
   top-heavy. Scoped modifier: do NOT change shared .intro-grid (Consulting
   uses it with a full-height lede). */
.intro-grid--bio {
  align-items: center;
}
.intro-grid--bio .prose {
  max-width: 52ch;
}
.headshot {
  margin: 0;
}
.headshot-img,
.headshot-monogram {
  width: 132px;
  height: 132px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.headshot-img {
  object-fit: cover;
  filter: grayscale(0.15) contrast(1.02);
}
.headshot-monogram {
  font-family: var(--serif);
  font-weight: 500;
  font-size: 2.7rem;
  letter-spacing: 0.01em;
  color: var(--water-deep);
  background: rgba(47, 90, 102, 0.08);
  border: 1px solid var(--hairline);
}
@media (max-width: 34rem) {
  .intro-grid {
    grid-template-columns: 1fr;
    gap: 20px;
  }
}

/* ---- Service pillars ------------------------------------------------ */

.pillars {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: clamp(28px, 5vw, 44px);
}
.pillar {
  padding-top: calc(var(--step) * 3);
  padding-left: 0;
  border-top: 1px solid var(--hairline);
  transition:
    border-color 240ms ease,
    padding-left 240ms ease;
}
.pillar:hover {
  border-top-color: var(--water);
  padding-left: 10px;
}

/* Staggered rise on load - motion-sensitive users see them static. */
@media (prefers-reduced-motion: no-preference) {
  .pillar {
    opacity: 0;
    transform: translateY(12px);
    animation: pillar-rise 520ms cubic-bezier(0.22, 1, 0.36, 1) forwards;
  }
  .pillar:nth-child(1) {
    animation-delay: 180ms;
  }
  .pillar:nth-child(2) {
    animation-delay: 250ms;
  }
  .pillar:nth-child(3) {
    animation-delay: 320ms;
  }
}
@keyframes pillar-rise {
  to {
    opacity: 1;
    transform: none;
  }
}

/* OpenShore is a landing page: its feature pillars must always be readable, never
   dependent on the entrance animation completing. Keep them visible from the
   first frame; the rise above is a pure enhancement where motion runs. */
.page--oscode .pillar {
  opacity: 1;
  transform: none;
  animation: none;
}
.pillar-name {
  font-family: var(--serif);
  font-weight: 500;
  font-size: 1.3rem;
  margin: 0 0 calc(var(--step) * 1.5);
  color: var(--ink);
}
.pillar-promise {
  font-family: var(--serif);
  font-size: 1.12rem;
  line-height: 1.45;
  color: var(--ink);
  margin: 0 0 calc(var(--step) * 1.5);
  max-width: 44ch;
}
.pillar-covers {
  margin: 0;
  color: var(--ink-soft);
  font-size: 0.96rem;
  max-width: 58ch;
}

/* ---- Infrastructure: the five components ---------------------------- */

.components {
  list-style: none;
  margin: clamp(28px, 5vw, 44px) 0 0;
  padding: 0;
}
.component {
  display: grid;
  grid-template-columns: 11rem 1fr;
  gap: clamp(8px, 2vw, 32px);
  align-items: baseline;
  padding: calc(var(--step) * 3) clamp(4px, 1.5vw, 14px);
  margin: 0 clamp(-4px, -1.5vw, -14px);
  border-top: 1px solid var(--hairline);
  border-radius: 6px;
  transition: background-color 220ms ease;
}
.component:last-child {
  border-bottom: 1px solid var(--hairline);
}
.component:hover {
  background-color: rgba(47, 90, 102, 0.04);
}
.component-name {
  font-family: var(--serif);
  font-size: 1.25rem;
  font-weight: 500;
  color: var(--ink);
}
.component-body {
  color: var(--ink-soft);
  font-size: 0.98rem;
  line-height: 1.55;
  max-width: 54ch;
}
@media (max-width: 34rem) {
  .component {
    grid-template-columns: 1fr;
    gap: 6px;
  }
}

/* ---- Edge callout --------------------------------------------------- */

.block--edge {
  padding: clamp(24px, 4vw, 36px);
  margin-left: clamp(-8px, -2vw, -24px);
  margin-right: clamp(-8px, -2vw, -24px);
  background: rgba(47, 90, 102, 0.05);
  border-radius: 10px;
}

/* ---- Landfall: flagship band, timeline, tracks ---------------------- */

.landfall .lede {
  max-width: 54ch;
}
.landfall-turn {
  margin-top: clamp(20px, 4vw, 32px);
  display: grid;
  gap: calc(var(--step) * 2);
}

/* Horizon-anchored timeline - the hairline is the shoreline, three nodes
   mark the phases. Plain grid; no load animation, so it's motion-safe. */
.voyage {
  list-style: none;
  margin: clamp(28px, 5vw, 44px) 0 0;
  padding: 0;
  display: grid;
  gap: clamp(22px, 4vw, 34px);
}
@media (min-width: 40rem) {
  .voyage {
    grid-template-columns: repeat(3, 1fr);
    gap: clamp(18px, 3vw, 30px);
  }
}
.waypoint {
  position: relative;
  padding-top: calc(var(--step) * 3);
  border-top: 1px solid var(--hairline);
}
.waypoint-node {
  position: absolute;
  top: -5px;
  left: 0;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--water);
  box-shadow: 0 0 0 4px var(--paper);
}
.waypoint-when {
  display: block;
  font-family: var(--sans);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--water-deep);
  font-variant-numeric: tabular-nums;
}
.waypoint-phase {
  display: block;
  font-family: var(--serif);
  font-size: 1.2rem;
  font-weight: 500;
  color: var(--ink);
  margin: calc(var(--step) * 1) 0;
}
.waypoint-body {
  display: block;
  color: var(--ink-soft);
  font-size: 0.94rem;
  line-height: 1.55;
}

.tracks {
  display: grid;
  gap: clamp(18px, 3vw, 26px);
}
@media (min-width: 40rem) {
  .tracks {
    grid-template-columns: 1fr 1fr;
  }
}
.track {
  padding: clamp(22px, 3vw, 30px);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  background: var(--paper);
  transition:
    border-color 240ms ease,
    transform 240ms ease;
}
.track:hover {
  border-color: var(--water);
  transform: translateY(-2px);
}
.track-audience {
  font-family: var(--sans);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 0 calc(var(--step) * 1.5);
}
.track-name {
  font-family: var(--serif);
  font-weight: 500;
  font-size: 1.35rem;
  color: var(--ink);
  margin: 0 0 calc(var(--step) * 1.5);
}
.track-promise {
  font-family: var(--serif);
  font-size: 1.08rem;
  line-height: 1.45;
  color: var(--ink);
  margin: 0 0 calc(var(--step) * 2.5);
}
.track-includes {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: calc(var(--step) * 1.5);
}
.track-includes li {
  position: relative;
  padding-left: 22px;
  color: var(--ink-soft);
  font-size: 0.95rem;
  line-height: 1.5;
}
.track-includes li::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 0.62em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--water);
}

/* Divider into the fractional practice (the second offer). */
.block--practice {
  margin-top: clamp(64px, 12vw, 120px);
}
.block--practice .horizon {
  margin-top: 0;
  margin-bottom: clamp(32px, 6vw, 56px);
}

/* ---- Proof rows (metric rail + outcome) ----------------------------- */

.registry-row--proof {
  display: grid;
  grid-template-columns: 8rem 1fr; /* wide enough that every metric label sits on one line */
  gap: clamp(16px, 3vw, 36px);
  align-items: baseline;
}
.proof-metric {
  display: flex;
  flex-direction: column;
}
.proof-metric-value {
  font-family: var(--serif);
  font-weight: 500;
  font-size: 1.95rem;
  line-height: 1;
  color: var(--water-deep);
  font-variant-numeric: tabular-nums;
}
.proof-metric-label {
  margin-top: 7px;
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.registry-role {
  margin: 0 0 calc(var(--step) * 1.5);
  color: var(--ink-faint);
  font-size: 0.92rem;
}
@media (max-width: 34rem) {
  .registry-row--proof {
    grid-template-columns: 1fr;
    gap: 10px;
  }
}

/* ---- Consulting router: doors + offers ------------------------------ */

.intro-bridge {
  margin-top: calc(var(--step) * 2);
  max-width: 52ch;
}

/* The top-of-page opener now that the flagship setup moved into its offer.
   A touch wider than the default lede so it breathes as the opener. */
.intro-lede {
  max-width: 48ch;
}

/* Credibility summary under the opener, distilled from the resume intro. */
.intro-summary {
  margin-top: clamp(18px, 3.5vw, 28px);
  max-width: 58ch;
}

/* How I operate: leadership tenets as a quiet numbered column, serif-set with
   deep-water counters. */
.tenets {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: calc(var(--step) * 1.5);
  counter-reset: tenet;
  max-width: 52ch;
}
.tenet {
  position: relative;
  padding-left: 2.4rem;
  counter-increment: tenet;
  font-family: var(--serif);
  font-size: 1.08rem;
  line-height: 1.4;
  color: var(--ink);
}
.tenet::before {
  content: counter(tenet);
  position: absolute;
  left: 0;
  top: 0.02em;
  font-family: var(--serif);
  font-size: 1rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--water-deep);
  width: 1.6rem;
  text-align: right;
}

/* The flagship setup, relocated into the Landfall for Founders detail. */
.offer-sub {
  margin-bottom: calc(var(--step) * 2.5);
}

/* The "Where are you?" chooser. Hidden in markup until router.js reveals it;
   no-JS users skip it entirely and read the full offer list below. */
.router[hidden] {
  display: none;
}
.doors {
  display: grid;
  gap: clamp(12px, 2vw, 18px);
}
@media (min-width: 44rem) {
  .doors {
    grid-template-columns: repeat(3, 1fr);
  }
}
.door {
  display: block;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
  padding: clamp(16px, 2.4vw, 22px);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  background: var(--paper);
  transition:
    border-color 240ms ease,
    transform 240ms ease,
    box-shadow 240ms ease,
    background-color 240ms ease;
}
.door:hover,
.door:focus-visible {
  border-color: var(--water);
  transform: translateY(-2px);
  outline: none;
}
.door:focus-visible {
  box-shadow: 0 0 0 2px var(--paper), 0 0 0 4px var(--water);
}
.door:active {
  transform: translateY(0) scale(0.99);
}
.door.is-active {
  border-color: var(--water);
  background: rgba(47, 90, 102, 0.06);
}
.door-label {
  display: block;
  font-family: var(--serif);
  font-size: 1.05rem;
  font-weight: 500;
  line-height: 1.3;
  color: var(--ink);
}
.door-hint {
  display: block;
  margin-top: calc(var(--step) * 1);
  font-size: 0.88rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

.router-reset {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: calc(var(--step) * 3);
  cursor: pointer;
  font-family: var(--sans);
  font-weight: 500;
  font-size: 0.9rem;
  color: var(--water-deep);
  background: none;
  border: none;
  padding: 0;
  transition: color 200ms ease;
}
.router-reset:hover,
.router-reset:focus-visible {
  color: var(--water);
}
.router-reset[hidden] {
  display: none;
}

.linklike {
  font: inherit;
  color: var(--water-deep);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  text-decoration: underline;
}
.linklike:hover {
  color: var(--water);
}

.offers-empty {
  color: var(--ink-soft);
  margin: 0 0 calc(var(--step) * 3);
}
.offers-empty[hidden] {
  display: none;
}

/* The offer list - one consistent skeleton per offer so the eye learns the
   rhythm once. Each is an expandable card; collapse only engages once the
   enhancement is live (.has-router), so no-JS keeps everything open. */
.offers {
  display: grid;
  gap: clamp(14px, 2.4vw, 20px);
  scroll-margin-top: 24px;
}
#offers {
  scroll-margin-top: 24px;
}
.offer {
  border: 1px solid var(--hairline);
  border-radius: 12px;
  background: var(--paper);
  overflow: hidden; /* clip summary hover + collapse to the rounded corners */
  transition: border-color 240ms ease;
}
.offer[hidden] {
  display: none;
}

/* Staggered reveal - matching offers rise in sequence when a door is picked,
   each a beat after the last. Motion-sensitive users get the content static. */
@media (prefers-reduced-motion: no-preference) {
  .has-router .offer.is-revealing {
    animation: offer-rise 460ms cubic-bezier(0.22, 1, 0.36, 1) both;
    animation-delay: calc(var(--reveal-i, 0) * 45ms);
  }
}
@keyframes offer-rise {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.offer--flagship {
  border-color: rgba(47, 90, 102, 0.35);
  background: rgba(47, 90, 102, 0.03);
}
.has-router .offer:hover {
  border-color: var(--water);
}

.offer-summary {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  width: 100%;
  text-align: left;
  cursor: default;
  font-family: inherit;
  background: none;
  border: none;
  padding: clamp(18px, 2.6vw, 26px);
}
.has-router .offer-summary {
  cursor: pointer;
  border-radius: 12px 12px 0 0;
  transition: background-color 200ms ease;
}
.has-router .offer.is-collapsed .offer-summary {
  border-radius: 12px;
}
.has-router .offer-summary:hover {
  background: rgba(47, 90, 102, 0.035);
}
.offer-summary:focus-visible {
  outline: 2px solid var(--water);
  outline-offset: -4px;
  border-radius: 12px;
}
.offer-head {
  min-width: 0;
}
.offer-segment {
  display: block;
  font-family: var(--sans);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: calc(var(--step) * 1);
}
.offer-name {
  display: block;
  font-family: var(--serif);
  font-size: 1.3rem;
  font-weight: 500;
  line-height: 1.25;
  color: var(--ink);
}

/* Pricing figure in a plan's summary row (OpenShore). Baseline-aligned with the
   plan name via the flex .offer-summary; stays on one line and never wraps. */
.offer-price {
  flex: none;
  font-family: var(--serif);
  font-size: 1.15rem;
  font-weight: 500;
  color: var(--water);
  white-space: nowrap;
}
.offer-flag {
  display: inline-block;
  vertical-align: middle;
  margin-left: 8px;
  font-family: var(--sans);
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--water-deep);
  background: rgba(47, 90, 102, 0.1);
  padding: 3px 7px;
  border-radius: 999px;
}

/* Chevron affordance - only meaningful when collapse is enabled. */
.offer-toggle {
  display: none;
  position: relative;
  flex: none;
  width: 14px;
  height: 14px;
  align-self: center;
}
.has-router .offer-toggle {
  display: inline-block;
}
.offer-toggle::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 8px;
  height: 8px;
  border-right: 1.6px solid var(--water);
  border-bottom: 1.6px solid var(--water);
  transform: rotate(45deg);
  transition: transform 260ms cubic-bezier(0.22, 1, 0.36, 1);
}
.offer:not(.is-collapsed) .offer-toggle::after {
  transform: rotate(-135deg);
}

/* Collapsible detail - animate the grid track from 0fr→1fr (height-safe,
   no magic max-height). Disabled entirely without the enhancement. */
.offer-detail {
  display: grid;
  grid-template-rows: 1fr;
  transition:
    grid-template-rows 420ms cubic-bezier(0.22, 1, 0.36, 1),
    opacity 300ms ease;
  opacity: 1;
}
.offer-detail-inner {
  overflow: hidden;
  min-height: 0;
  padding: 0 clamp(18px, 2.6vw, 26px) clamp(22px, 3vw, 30px);
}
.has-router .offer.is-collapsed > .offer-detail {
  grid-template-rows: 0fr;
  opacity: 0;
}

.offer-promise {
  font-family: var(--serif);
  font-size: 1.12rem;
  line-height: 1.45;
  color: var(--ink);
  margin: 0 0 calc(var(--step) * 3);
  max-width: 48ch;
}
.offer-slot {
  margin: 0 0 calc(var(--step) * 3);
}
.offer-slot-label {
  display: block;
  font-family: var(--sans);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 0 calc(var(--step) * 1.5);
}
.offer-metaline .offer-slot-label {
  display: inline;
  margin-right: 8px;
}

.fit-markers {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: calc(var(--step) * 1);
}
.fit-markers li {
  position: relative;
  padding-left: 22px;
  color: var(--ink-soft);
  font-size: 0.95rem;
  line-height: 1.5;
}
.fit-markers li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 0.55em;
  width: 8px;
  height: 8px;
  border-right: 1.4px solid var(--water);
  border-bottom: 1.4px solid var(--water);
  transform: rotate(45deg);
}

.offer-metaline {
  border-top: 1px solid var(--hairline);
  padding-top: calc(var(--step) * 2.5);
}
.offer-metaline .offer-slot {
  color: var(--ink-soft);
  font-size: 0.96rem;
  line-height: 1.55;
  max-width: 58ch;
}
.offer-metaline .offer-outcome {
  margin-bottom: calc(var(--step) * 3);
}

/* Flagship detail keeps its narrative + voyage timeline. */
.offer--flagship .landfall-turn {
  margin-top: 0;
  margin-bottom: calc(var(--step) * 2);
}

@media (prefers-reduced-motion: reduce) {
  .offer-detail {
    transition: none;
  }
  .offer-toggle::after {
    transition: none;
  }
  .door {
    transition: none;
  }
}

/* ---- Scroll-reveal (static content settles in on entry) ------------- */

/* Base state applied by router.js only (no-JS keeps everything visible), and
   neutralized for reduced-motion below. */
.reveal {
  opacity: 0;
  transform: translateY(10px);
  will-change: opacity, transform; /* released via JS on transitionend */
  transition:
    opacity 560ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 560ms cubic-bezier(0.22, 1, 0.36, 1);
  transition-delay: calc(var(--rvi, 0) * 45ms);
}
.reveal.is-in {
  opacity: 1;
  transform: none;
}
@media (prefers-reduced-motion: reduce) {
  .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ---- Persistent consultation CTA (floating) ------------------------- */

.consult-fab {
  position: fixed;
  right: clamp(16px, 4vw, 32px);
  bottom: calc(env(safe-area-inset-bottom, 0px) + clamp(16px, 4vw, 28px));
  z-index: 50;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 13px 20px;
  border-radius: 999px;
  background: var(--water);
  background-image: none; /* cancel the global link underline gradient */
  color: var(--paper);
  font-family: var(--sans);
  font-weight: 500;
  font-size: 0.95rem;
  line-height: 1;
  letter-spacing: 0.005em;
  box-shadow:
    0 1px 2px rgba(28, 42, 51, 0.16),
    0 8px 22px rgba(28, 42, 51, 0.22);
  transition:
    transform 220ms cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 220ms ease,
    background-color 220ms ease,
    opacity 300ms ease;
}

/* Entrance: fade + rise in a beat after load. `backwards` fill holds the from-
   state during the delay (no flash) and drops after (so hover/hide transforms
   stay free). Motion-only. */
@media (prefers-reduced-motion: no-preference) {
  .consult-fab {
    animation: fab-in 460ms cubic-bezier(0.22, 1, 0.36, 1) 420ms backwards;
  }
}
@keyframes fab-in {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* Yields while the contact section is in view (redundant + would overlap the
   colophon). Higher specificity than :hover, and pointer-events off, so it
   can't be fought by a stray hover. */
.consult-fab.is-at-contact {
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
}
.consult-fab-icon {
  transition: transform 200ms ease;
}
.consult-fab:hover .consult-fab-icon,
.consult-fab:focus-visible .consult-fab-icon {
  transform: translateX(1px);
}
.consult-fab:hover,
.consult-fab:focus-visible {
  background: var(--water-deep);
  background-image: none;
  color: var(--paper);
  transform: translateY(-2px);
  box-shadow:
    0 2px 4px rgba(28, 42, 51, 0.18),
    0 14px 30px rgba(28, 42, 51, 0.26);
}
.consult-fab:active {
  transform: translateY(0) scale(0.98);
}
.consult-fab:focus-visible {
  outline: 2px solid var(--water);
  outline-offset: 3px;
}
.consult-fab-icon {
  flex: none;
}
.consult-fab-label {
  white-space: nowrap;
}

/* On narrow screens collapse to a clean icon-only tap target so it never
   crowds the content; the accessible name stays on the anchor. */
@media (max-width: 30rem) {
  .consult-fab {
    gap: 0;
    padding: 15px;
  }
  .consult-fab-label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .consult-fab {
    transition: none;
  }
}

/* ---- Colophon ------------------------------------------------------- */

.colophon {
  margin-top: clamp(56px, 10vw, 104px);
  color: var(--ink-faint);
  font-size: 0.82rem;
}
.colophon p {
  margin: 0;
}

/* ---- Motion / accessibility ----------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .horizon {
    animation: none;
    transform: scaleX(1);
  }
  a {
    transition: none;
  }
}

@media (max-width: 34rem) {
  .contact-label {
    flex-basis: 100%;
  }
  .registry-meta {
    width: 100%;
    justify-content: flex-start;
  }
}

/* ---- OpenShore web billing (auth bar + login dialog) ------------------- */
/* The purchase surface: sign in, buy seats, manage a subscription, all on
   the web so Apple takes no cut and the app carries no in-app purchase. Uses
   the page's existing paper/ink/water palette. */
.masthead-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--step);
}
.oscode-auth {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}
.oscode-auth-in {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.oscode-auth-email {
  font-family: var(--sans);
  font-size: 0.82rem;
  color: var(--ink-soft);
}
.oscode-auth-btn {
  font-family: var(--sans);
  font-size: 0.85rem;
  font-weight: 500;
  color: #fff;
  background: var(--water);
  border: 1px solid var(--water);
  border-radius: 999px;
  padding: 0.4rem 0.9rem;
  cursor: pointer;
  transition:
    background 150ms ease,
    color 150ms ease;
}
.oscode-auth-btn:hover {
  background: var(--water-deep);
}
.oscode-auth-btn.ghost {
  color: var(--water-deep);
  background: transparent;
  border-color: rgba(47, 90, 102, 0.35);
}
.oscode-auth-btn.ghost:hover {
  background: rgba(47, 90, 102, 0.08);
}

/* A .block-cta rendered as a real <button> (the commercial plan CTAs). */
button.block-cta {
  border: none;
  background: transparent;
  cursor: pointer;
  padding: 0;
  font: inherit;
}

.oscode-login {
  border: none;
  border-radius: 16px;
  padding: clamp(1.4rem, 4vw, 2rem);
  width: min(92vw, 26rem);
  max-height: min(88dvh, 640px);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  background: var(--paper);
  color: var(--ink);
  box-shadow: 0 24px 70px rgba(28, 42, 51, 0.28);
}
.oscode-login::backdrop {
  background: rgba(28, 42, 51, 0.45);
}
.oscode-login-close {
  position: absolute;
  top: 0.6rem;
  right: 0.8rem;
  border: none;
  background: none;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--ink-faint);
  cursor: pointer;
}
.oscode-login-title {
  font-family: var(--serif, var(--sans));
  margin: 0 0 0.3rem;
}
.oscode-login-sub {
  font-family: var(--sans);
  font-size: 0.86rem;
  color: var(--ink-soft);
  margin: 0 0 1.1rem;
}
.oscode-field {
  display: block;
  margin-bottom: 0.8rem;
}
.oscode-field span {
  display: block;
  font-family: var(--sans);
  font-size: 0.78rem;
  color: var(--ink-faint);
  margin-bottom: 0.3rem;
}
.oscode-field input {
  width: 100%;
  font: inherit;
  font-size: 0.95rem;
  color: var(--ink);
  background: #fff;
  border: 1px solid rgba(28, 42, 51, 0.18);
  border-radius: 10px;
  padding: 0.6rem 0.75rem;
}
.oscode-field input:focus-visible {
  outline: 2px solid var(--water);
  outline-offset: 1px;
}
.oscode-login-error {
  font-family: var(--sans);
  font-size: 0.82rem;
  color: #c0392b;
  min-height: 1.1rem;
  margin: 0.2rem 0 0.4rem;
}
.oscode-login .oscode-login-submit {
  display: block;
  width: 100%;
  margin-top: 0.2rem;
  text-align: center;
  color: #fff;
  background: var(--water);
  border: none;
  border-radius: 999px;
  padding: 0.7rem 1rem;
  cursor: pointer;
}
.oscode-login .oscode-login-submit:hover {
  background: var(--water-deep);
}
.oscode-login-toggle {
  display: block;
  width: 100%;
  margin-top: 0.7rem;
  border: none;
  background: none;
  font-family: var(--sans);
  font-size: 0.85rem;
  color: var(--water-deep);
  cursor: pointer;
}

/* ---- OpenShore billing: polish pass ----------------------------------- */
/* Pressed-state "give" on every control. */
.oscode-auth-btn:active,
button.block-cta:active,
.oscode-login .oscode-login-submit:active {
  transform: scale(0.97);
}
.oscode-auth-btn,
.oscode-login .oscode-login-submit {
  transition:
    background 150ms ease,
    transform 80ms ease;
}
button.block-cta {
  transition: transform 80ms ease;
}
.oscode-auth-btn:focus-visible {
  outline: 2px solid var(--water);
  outline-offset: 2px;
}

/* Auth control resolves in with a soft fade rather than popping. */
.oscode-auth > * {
  animation: oscode-fade 220ms ease both;
}

/* Login sheet springs in like a native modal (and its backdrop fades). */
.oscode-login {
  transition:
    opacity 220ms ease,
    transform 240ms cubic-bezier(0.32, 0.72, 0, 1),
    overlay 240ms allow-discrete,
    display 240ms allow-discrete;
}
.oscode-login[open] {
  opacity: 1;
  transform: translateY(0) scale(1);
}
@starting-style {
  .oscode-login[open] {
    opacity: 0;
    transform: translateY(10px) scale(0.98);
  }
}
.oscode-login::backdrop {
  transition:
    opacity 220ms ease,
    overlay 220ms allow-discrete,
    display 220ms allow-discrete;
}
.oscode-login[open]::backdrop {
  opacity: 1;
}
@starting-style {
  .oscode-login[open]::backdrop {
    opacity: 0;
  }
}

/* Error text eases in instead of snapping. */
.oscode-login-error {
  opacity: 0;
  transition: opacity 150ms ease;
}
.oscode-login-error.is-shown {
  opacity: 1;
}

/* Return-from-Stripe confirmation banner. */
.oscode-banner {
  margin: 0 auto 1.4rem;
  max-width: 42rem;
  border-radius: 12px;
  background: rgba(47, 90, 102, 0.1);
  color: var(--water-deep);
  border: 1px solid rgba(47, 90, 102, 0.25);
  font-family: var(--sans);
  font-size: 0.95rem;
  text-align: center;
  padding: 0.8rem 1rem;
  opacity: 0;
  transform: translateY(-6px);
  transition:
    opacity 300ms ease,
    transform 300ms cubic-bezier(0.32, 0.72, 0, 1);
}
.oscode-banner.is-shown {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .oscode-auth-btn:active,
  button.block-cta:active,
  .oscode-login .oscode-login-submit:active {
    transform: none;
  }
  .oscode-auth > *,
  .oscode-login,
  .oscode-login::backdrop,
  .oscode-banner {
    animation: none;
    transition: none;
  }
}

@keyframes oscode-fade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
