/* OpenShore: "Nightshore". A dark theme layered over styles.css by load order
   (base.njk links this file second, unconditionally, since this whole site is
   the OpenShore page now). Spotify's energy (near-black ground, one hot
   accent, oversized tight Inter, cards that lift) translated to OpenShore:
   water-teal on abyss, a teal-to-amber tier spectrum, the horizon glow as the
   wave, and one surviving line of Fraunces so the family shows.
   No em dashes in customer copy (OpenShore rule); this file is CSS only. */

:root {
  --abyss: #0b1417; /* page ground: water-tinted near-black */
  --abyss-2: #10202a; /* base card */
  --surface: #16283199; /* elevated glass card */
  --surface-solid: #182c36; /* card hover */
  --line: #24424d; /* hairline on dark */
  --paper: #f6f4ef; /* warm near-white text, never pure #fff */
  --mist: #a9bac0; /* secondary text */
  --faint: #81949c; /* meta / labels; lifted for AA on small-caps over abyss */
  --wave: #5bb6cb; /* bright accent: CTAs, glow, local work */
  --wave-2: #2f5a66; /* deep teal gradient partner */
  --amber: #e0902f; /* cloud / spend / flagship */
  --spring: cubic-bezier(0.34, 1.56, 0.64, 1);
}

body {
  background: var(--abyss);
  color: var(--paper);
}

/* Site chrome goes dark to match. */
.sitenav {
  background: rgba(11, 20, 23, 0.72);
  border-bottom: 1px solid var(--line);
  backdrop-filter: saturate(140%) blur(16px);
  -webkit-backdrop-filter: saturate(140%) blur(16px);
}
/* The OpenShore header is a real bar: pad the top, then drop the bottom padding
   to zero so the tab row seats on the header's own border line (the shared
   .sitenav already does this; .sitenav--oscode restores it after its earlier
   even-padding override). */
.sitenav--oscode {
  padding-block: clamp(14px, 3.6vw, 20px) 0;
}
.brand-word {
  color: var(--paper);
}
/* The OpenShore header stacks the brand: an icon-plus-wordmark that links home,
   with a quiet "brought to you by" line crediting Open Shore back out to the
   parent site. The tab row sits below it. */
.brand--oscode {
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
  margin-bottom: clamp(12px, 3vw, 18px);
}
.brand-home {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
  background-image: none;
  line-height: 1;
}
.brand--oscode .brand-word {
  font-size: 1.5rem;
  line-height: 1;
}
.brand-sub {
  font-family: var(--sans);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--faint);
  text-decoration: none;
  background-image: none;
  transition: color 160ms ease;
}
.brand-sub:hover,
.brand-sub:focus-visible {
  color: var(--wave);
}
/* The logo tile was dark slate on a near-black page, so it vanished. Fill it
   with the brand teal and invert the mark to abyss, so it reads like a bright
   app icon and anchors the header. A soft teal glow lifts it off the bar. */
.brand--oscode .brand-mark {
  width: 46px;
  height: 46px;
  border-radius: 11px;
  filter: drop-shadow(0 6px 16px rgba(91, 182, 203, 0.28));
}
.brand--oscode .brand-mark rect {
  fill: var(--wave);
}
.brand--oscode .brand-mark line,
.brand--oscode .brand-mark path {
  stroke: var(--abyss);
}
/* Tab row, dark. The base stylesheet lays out the scrollable strip; here it
   takes the Nightshore hairline and the teal active underline. */
.sitenav--oscode .sitenav-tabs {
  border-bottom-color: var(--line);
}
.sitenav-tab {
  color: var(--mist);
  font-weight: 600;
}
.sitenav-tab:hover,
.sitenav-tab:focus-visible,
.sitenav-tab.is-active {
  color: var(--paper);
}
.sitenav-tab.is-active {
  border-bottom-color: var(--wave);
}

/* ---- Hero ----------------------------------------------------------- */
.masthead {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  /* The header bar now sits above the hero, so the top no longer carries the
     full page-opener padding; the bottom is trimmed so the shore glow does not
     leave a tall empty band under the buttons. */
  padding-block: clamp(1.75rem, 5vw, 3.25rem) clamp(1.75rem, 4.5vw, 3rem);
}
/* The auth control is the only thing left in the top row now that the header
   carries the wordmark, so it sits right-aligned with clear air before the
   headline. */
.masthead-top {
  justify-content: flex-end;
  min-height: 2.2rem;
  margin-bottom: clamp(1.4rem, 4vw, 2.25rem);
}
/* The auth slot is empty until someone is signed in (openshore-app.js only
   fills it when logged in; signing in is otherwise prompted at checkout). While
   it is empty, collapse the whole top row so the hero starts at the top with no
   stray gap where the old "Log in" button used to sit. */
.masthead-top:has(> .oscode-auth:empty) {
  display: none;
}
/* The wave, scaled to a scene: a low shore glow behind the headline. */
.masthead::before {
  content: "";
  position: absolute;
  inset: -10% -20% -30% -20%;
  z-index: -1;
  background:
    radial-gradient(120% 62% at 50% 92%, rgba(91, 182, 203, 0.26), transparent 60%),
    radial-gradient(80% 50% at 82% 20%, rgba(224, 144, 47, 0.1), transparent 55%),
    linear-gradient(180deg, #0b1417, #10202a 70%);
  animation: nightshore-breathe 12s ease-in-out infinite;
}
.wordmark-unit {
  color: var(--faint);
  font-family: var(--sans);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-size: 0.75rem;
}
.identity {
  font-family: var(--sans);
  font-weight: 900;
  font-size: clamp(3rem, 9vw, 6.75rem);
  letter-spacing: -0.045em;
  line-height: 0.94;
  color: var(--paper);
  text-wrap: balance;
}
/* A subpage keeps the hero's shore glow but not its billboard type: the
   landing page's identity line is the product's one shout, and repeating it at
   full size on Terms of Use would flatten the difference. */
.masthead--sub .identity {
  font-size: clamp(2.25rem, 5vw, 3.5rem);
  letter-spacing: -0.035em;
}
.masthead--sub .lede {
  margin-top: 1.1rem;
}
.identity-coda {
  display: block;
  margin-top: 1.1rem;
  font-family: var(--serif); /* the one surviving line of Fraunces */
  font-weight: 400;
  font-style: italic;
  font-size: clamp(1.05rem, 2.4vw, 1.4rem);
  letter-spacing: 0;
  line-height: 1.3;
  color: var(--mist);
}
/* The ownership payoff, teal, so the one serif line reads as a promise. */
.coda-accent {
  color: var(--wave);
  font-style: italic;
}
.horizon {
  height: 2px;
  margin-top: clamp(1.25rem, 3vw, 1.6rem);
  background: linear-gradient(90deg, var(--wave), transparent);
  transform-origin: left;
  animation: nightshore-draw 700ms ease-out both;
}
/* Give the first viewport a thumb target: a teal pill to the plans, a quiet
   ghost to the how-it-works band. Sits close under the divider so the hero
   reads as one unit instead of leaving a dead band. */
.hero-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-top: clamp(1.25rem, 3vw, 1.6rem);
}
.hero-cta {
  margin-top: 0;
}
.hero-cta-ghost {
  display: inline-block;
  border-radius: 999px;
  padding: 13px 24px;
  border: 1px solid var(--line);
  color: var(--paper);
  background: transparent;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 0.95rem;
  transition:
    border-color 180ms ease,
    background 180ms ease;
}
.hero-cta-ghost:hover,
.hero-cta-ghost:focus-visible {
  border-color: var(--wave);
  background: rgba(91, 182, 203, 0.08);
  color: var(--paper);
}
/* Both hero pills share one box so they sit on the same row at the same height,
   each centered on its own text. The filled pill carried no border and 14px of
   vertical padding; the ghost carried a 1px border and 13px. That mix rendered
   two slightly different heights whose centers drifted apart. Fold both into one
   inline-flex box with a shared min-height (border-box absorbs the ghost's 1px),
   so they align to the pixel and clear the 44px touch target. */
.hero-actions .block-cta,
.hero-actions .hero-cta-ghost {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.45em;
  margin-top: 0;
  min-height: 50px;
  padding-block: 0;
  font-size: 0.98rem;
  line-height: 1;
}
.hero-actions .block-cta {
  padding-inline: 30px;
}
.hero-actions .hero-cta-ghost {
  padding-inline: 26px;
}

/* ---- Body sections -------------------------------------------------- */
.block {
  border: none;
}
.eyebrow {
  font-family: var(--sans);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 0.75rem;
  color: var(--wave);
}
.lede {
  color: var(--paper);
  font-family: var(--sans);
  font-weight: 440;
  font-size: clamp(1.15rem, 2.6vw, 1.6rem);
  line-height: 1.4;
}
.prose {
  color: var(--mist);
}
/* The ethics stance: two short paragraphs that need air between them. The
   base .prose carries no margin so a statement can stack tight; scope the
   spacing to the stance rather than restyling every paragraph. */
.stance .prose + .prose {
  margin-top: 0.85rem;
}
.stance + .prose {
  margin-top: 1rem;
}

/* ---- Privacy policy: plain lists with air --------------------------- */
.policy ul {
  margin: 0.75rem 0 0;
  padding-left: 1.2rem;
  color: var(--mist);
}
.policy li + li {
  margin-top: 0.6rem;
}
.policy .prose + .prose,
.policy ul + .prose {
  margin-top: 0.85rem;
}

/* ---- Pillars: glass cards that lift --------------------------------- */
/* "Get OpenShore" tile grid. Same shape as .pillars (glass card, spring lift
   on hover) with a glyph well and a status chip added, mirroring the visual
   grammar of uki.audio's own get-app tiles (styles.css there) re-themed onto
   Nightshore's dark surface instead of Uki's cream paper. A tile without a
   live href renders as .is-soon: dimmed, no hover, a neutral chip instead of
   the wave-colored "Get" one, so a not-yet-real download never looks
   clickable. */
.get-app {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 14px;
  list-style: none;
  margin: 24px 0 0;
  padding: 0;
  text-align: left;
}
.get-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 8px;
  height: 100%;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 1.2rem 1.15rem;
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  text-decoration: none;
  transition:
    transform 240ms var(--spring),
    border-color 200ms ease,
    box-shadow 240ms ease;
  will-change: transform;
}
.get-tile.is-soon {
  cursor: default;
  opacity: 0.55;
}
.get-glyph {
  width: 38px;
  height: 38px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  color: var(--wave);
  background: rgba(91, 182, 203, 0.1);
  border: 1px solid var(--line);
}
.get-glyph svg {
  width: 21px;
  height: 21px;
}
.get-label {
  font-family: var(--sans);
  font-weight: 800;
  font-size: 1.02rem;
  letter-spacing: -0.02em;
  color: var(--paper);
}
.get-sub {
  font-size: 0.78rem;
  line-height: 1.4;
  color: var(--faint);
}
.get-chip {
  margin-top: auto;
  align-self: flex-start;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--mist);
  background: rgba(169, 186, 192, 0.12);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 4px 10px;
  white-space: nowrap;
}
.get-tile-live:hover,
.get-tile-live:focus-within {
  transform: translateY(-4px);
  border-color: var(--wave);
  box-shadow: 0 20px 50px -20px rgba(0, 0, 0, 0.6);
}
.get-tile-live:hover .get-glyph,
.get-tile-live:focus-within .get-glyph {
  background: rgba(91, 182, 203, 0.18);
}
/* Download is the one action; GitHub and the other file sit beside it,
   quiet, for anyone who wants the release notes or a different package. */
.get-actions {
  margin-top: auto;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 14px;
}
.get-actions .get-chip {
  margin-top: 0;
  text-decoration: none;
  cursor: pointer;
}
.get-chip-live {
  color: var(--abyss);
  background: var(--wave);
  border-color: var(--wave);
  font-size: 11px;
  padding: 6px 14px;
  transition: filter 160ms ease;
}
.get-chip-live:hover {
  filter: brightness(1.08);
}
.get-chip-live:focus-visible,
.get-link:focus-visible {
  outline: 2px solid var(--wave);
  outline-offset: 2px;
}
.get-link {
  font-size: 0.78rem;
  color: var(--mist);
  text-decoration: underline;
  text-decoration-color: rgba(169, 186, 192, 0.35);
  text-underline-offset: 3px;
}
.get-link:hover {
  color: var(--paper);
  text-decoration-color: currentColor;
}
@media (prefers-reduced-motion: reduce) {
  .get-tile-live {
    transition: none;
  }
  .get-tile-live:hover,
  .get-tile-live:focus-within {
    transform: none;
  }
}

.pillars {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 14px;
}
.pillar {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 1.4rem 1.3rem;
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  transition:
    transform 240ms var(--spring),
    border-color 200ms ease,
    box-shadow 240ms ease;
  will-change: transform;
}
/* A ghost wave echoing the brand mark, so each pillar reads as a system, not a
   text box. Faint at rest, it surfaces with the card on hover. */
.pillar::before {
  content: "";
  position: absolute;
  top: 14px;
  right: 14px;
  width: 26px;
  height: 26px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32' fill='none' stroke='%235bb6cb' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='7' y1='11' x2='25' y2='11'/%3E%3Cpath d='M7 19q4.5-3.3 9 0t9 0'/%3E%3C/svg%3E")
    center / contain no-repeat;
  opacity: 0.14;
  transition: opacity 200ms ease;
  pointer-events: none;
}
.pillar:hover {
  transform: translateY(-6px);
  border-color: var(--wave);
  box-shadow: 0 24px 60px -20px rgba(0, 0, 0, 0.6);
}
.pillar:hover::before {
  opacity: 0.9;
}
.pillar-name {
  font-family: var(--sans);
  font-weight: 800;
  font-size: 1.15rem;
  letter-spacing: -0.02em;
  color: var(--paper);
}
.pillar-promise {
  color: var(--paper);
}
.pillar-covers {
  color: var(--faint);
}

/* ---- How it works: numbered band ------------------------------------ */
.components {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 18px;
  counter-reset: step;
  list-style: none;
  padding: 0;
}
.component {
  position: relative;
  counter-increment: step;
  /* The base sheet lays a step out as a label | body row (11rem + 1fr), which
     inside one of these narrow grid cells squeezes the body into a sliver.
     Stack the name over the body instead. */
  display: block;
  padding-top: 3.4rem;
  border: none;
}
.component:last-child {
  border-bottom: none;
}
.component::before {
  content: counter(step, decimal-leading-zero);
  position: absolute;
  top: 0;
  left: 0;
  font-family: var(--sans);
  font-weight: 800;
  font-size: 3.2rem;
  letter-spacing: -0.04em;
  color: transparent;
  -webkit-text-stroke: 1.5px var(--wave);
}
.component-name {
  display: block;
  margin-bottom: 0.35rem;
  font-family: var(--sans);
  font-weight: 800;
  font-size: 1.2rem;
  letter-spacing: -0.02em;
  color: var(--paper);
}
.component-body {
  display: block;
  color: var(--mist);
}

/* ---- Plans: the pricing wall with a teal-to-amber spectrum ---------- */
.offers {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 16px;
  align-items: start;
}
.offer {
  position: relative;
  overflow: hidden;
  background: var(--abyss-2);
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 1.4rem 1.3rem 1.5rem;
  transition:
    transform 240ms var(--spring),
    border-color 200ms ease,
    box-shadow 240ms ease;
}
/* The spectrum: each tier's top spine ramps cool teal (Personal) to warm
   amber (Scale), so the rack reads as a scale of scale. */
.offer::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: var(--wave);
}
/* Each tier owns its spine hue via `color`, so the ::before spine AND the
   hover inset-bloom below both pick it up from currentColor and the rack lights
   in its own tier color under the cursor. */
.offers .offer:nth-child(1) {
  color: #4bd0c6;
}
.offers .offer:nth-child(2) {
  color: #5bb6cb;
}
.offers .offer:nth-child(3) {
  color: #6f9fbf;
}
.offers .offer:nth-child(4) {
  color: #b58a5e;
}
.offers .offer:nth-child(5) {
  color: var(--amber);
}
.offer::before {
  background: currentColor;
}
.offer:hover {
  transform: translateY(-6px);
  box-shadow:
    0 24px 60px -22px rgba(0, 0, 0, 0.65),
    inset 0 2px 0 0 currentColor;
}
.offer--flagship {
  border-color: var(--amber);
  transform: translateY(-8px);
  box-shadow: 0 30px 80px -28px rgba(224, 144, 47, 0.35);
}
.offer--flagship:hover {
  transform: translateY(-12px);
}
.offer-segment {
  font-family: var(--sans);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: 0.7rem;
  color: var(--faint);
}
.offer-name {
  font-family: var(--sans);
  font-weight: 800;
  font-size: 1.35rem;
  letter-spacing: -0.02em;
  color: var(--paper);
}
.offer-flag {
  display: inline-block;
  margin-left: 0.5rem;
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  background: rgba(224, 144, 47, 0.16);
  color: var(--amber);
  font-family: var(--sans);
  font-weight: 700;
  font-size: 0.68rem;
  letter-spacing: 0.02em;
  vertical-align: middle;
  white-space: nowrap;
}
.offer-price {
  font-family: var(--sans);
  font-weight: 800;
  font-size: 2.25rem;
  letter-spacing: -0.02em;
  color: var(--paper);
}
/* A short line under a price that is not the final one (Plus in
   pre-release), so the collapsed card never reads as a second free tier. */
.offer-price-note {
  display: block;
  margin-top: 0.2rem;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0;
  line-height: 1.3;
  color: var(--faint);
  text-align: right;
  white-space: normal;
  max-width: 9.5rem;
  margin-left: auto;
}
.offer-promise {
  color: var(--mist);
}
.offer-slot-label {
  font-family: var(--sans);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-size: 0.68rem;
  color: var(--faint);
}
.track-includes {
  color: var(--mist);
}
.track-includes li::marker {
  color: var(--wave);
}
/* Fine print under a card CTA (e.g. Personal's App Store note). */
.offer-fine {
  margin-top: 0.7rem;
  font-family: var(--sans);
  font-size: 0.82rem;
  line-height: 1.4;
  color: var(--faint);
}

/* Trust row under the pricing rack: three quiet promises. The same quiet
   label-plus-line shape carries the mission's promises and the "Everything
   inside" feature list (.why-list), so conviction and inventory both read as
   lists, not as more cards. */
.offer-reassure,
.why-list {
  list-style: none;
  margin: 22px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 14px;
}
.offer-reassure li,
.why-list li {
  font-family: var(--sans);
  font-size: 0.9rem;
  line-height: 1.45;
  color: var(--mist);
}
.offer-reassure strong,
.why-list strong {
  display: block;
  color: var(--paper);
  font-weight: 700;
}
/* The feature list is longer than three; give its rows a hairline so eleven
   entries scan as a grid rather than a wall. */
.why-list li {
  padding-top: 12px;
  border-top: 1px solid var(--line);
}

/* ---- Pill CTAs ------------------------------------------------------ */
.block-cta,
button.block-cta {
  display: inline-block;
  margin-top: 1.2rem;
  border-radius: 999px;
  padding: 14px 30px;
  background: var(--wave);
  color: var(--abyss);
  font-family: var(--sans);
  font-weight: 700;
  font-size: 0.98rem;
  background-image: none;
  transition:
    transform 120ms ease,
    filter 150ms ease;
}
.block-cta:hover,
.block-cta:focus-visible {
  color: var(--abyss);
  transform: scale(1.045);
  filter: brightness(1.06);
  background-image: none;
}
.block-cta:active {
  transform: scale(0.97);
}
.offer--flagship .block-cta {
  background: var(--amber);
}
.block-cta span {
  color: inherit;
}

/* ---- Contact / colophon -------------------------------------------- */
.contact-label,
.colophon {
  color: var(--faint);
}
.colophon a,
.contact-line a {
  color: var(--wave);
}

/* ---- Auth surfaces (JS-injected) ----------------------------------- */
.oscode-auth-btn {
  background: var(--wave);
  border-color: var(--wave);
  color: var(--abyss);
}
.oscode-auth-btn:hover {
  background: var(--wave);
  filter: brightness(1.08);
}
.oscode-auth-btn.ghost {
  background: transparent;
  color: var(--paper);
  border-color: var(--mist);
}
.oscode-auth-btn.ghost:hover {
  background: rgba(246, 244, 239, 0.08);
  filter: none;
}
.oscode-auth-email {
  color: var(--mist);
}

.oscode-login {
  background: var(--abyss-2);
  color: var(--paper);
  border: 1px solid var(--line);
  border-radius: 24px;
  box-shadow: 0 40px 120px -30px #000;
}
.oscode-login::backdrop {
  background: rgba(5, 10, 12, 0.82);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}
.oscode-login-title {
  font-family: var(--sans);
  font-weight: 800;
  color: var(--paper);
}
.oscode-login-sub {
  color: var(--mist);
}
.oscode-field span {
  color: var(--faint);
}
.oscode-field input {
  background: var(--abyss);
  color: var(--paper);
  border-color: var(--line);
}
.oscode-field input:focus-visible {
  outline-color: var(--wave);
}
.oscode-login .oscode-login-submit {
  background: var(--wave);
  color: var(--abyss);
}
.oscode-login .oscode-login-submit:hover {
  filter: brightness(1.06);
}
.oscode-login-toggle {
  color: var(--mist);
}

.oscode-banner {
  background: linear-gradient(90deg, rgba(224, 144, 47, 0.18), transparent);
  border: 1px solid var(--amber);
  color: var(--paper);
}

/* ---- FAB ------------------------------------------------------------ */
.consult-fab {
  background: var(--wave);
  color: var(--abyss);
  /* Quiet at rest so it does not compete with the teal CTAs; blooms on hover. */
  box-shadow: 0 10px 30px -8px rgba(91, 182, 203, 0.32);
  transition:
    transform 160ms ease,
    box-shadow 180ms ease;
}
.consult-fab:hover {
  transform: scale(1.05);
  box-shadow: 0 12px 34px -8px rgba(91, 182, 203, 0.5);
}

/* ---- Motion --------------------------------------------------------- */
@keyframes nightshore-breathe {
  0%,
  100% {
    opacity: 0.85;
  }
  50% {
    opacity: 1;
  }
}
@keyframes nightshore-draw {
  from {
    transform: scaleX(0);
  }
  to {
    transform: scaleX(1);
  }
}

@media (prefers-reduced-motion: reduce) {
  .masthead::before,
  .horizon {
    animation: none;
  }
  .pillar,
  .offer,
  .block-cta,
  .consult-fab {
    transition: none;
  }
  .pillar:hover,
  .offer:hover,
  .block-cta:hover,
  .block-cta:active {
    transform: none;
  }
}

/* ==== Tab pages (LLM Choice, Privacy, Sustainability, Self-Hosting) ====
   These focused pages share the Platform page's vocabulary (.block, .eyebrow,
   .lede, .why-list, .pillars, .components) and add three things: an editorial
   subpage hero, a text-and-visual split, and a figure wrapper for the guiding
   diagrams and phone mockups. */

/* ---- Subpage hero: Fraunces, quieter than the home billboard ---------- */
.subhero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: clamp(1.4rem, 4.5vw, 2.75rem) clamp(1.6rem, 4vw, 2.75rem);
}
.subhero::before {
  content: "";
  position: absolute;
  inset: -30% -20% -40% -20%;
  z-index: -1;
  background:
    radial-gradient(110% 60% at 20% 8%, rgba(91, 182, 203, 0.18), transparent 58%),
    radial-gradient(70% 46% at 92% 0%, rgba(224, 144, 47, 0.08), transparent 55%);
}
.subhero .eyebrow {
  display: block;
  margin-bottom: 0.7rem;
}
.subhero h1 {
  font-family: var(--serif);
  font-weight: 480;
  font-size: clamp(2.3rem, 6.4vw, 3.9rem);
  line-height: 1.03;
  letter-spacing: -0.02em;
  color: var(--paper);
  text-wrap: balance;
}
.subhero .subhead {
  margin-top: 1.05rem;
  max-width: 40rem;
  color: var(--mist);
  font-family: var(--sans);
  font-size: clamp(1.1rem, 2.5vw, 1.4rem);
  line-height: 1.42;
}

/* ---- Text + visual split -------------------------------------------- */
.split {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1.4rem, 4vw, 2.5rem);
  align-items: center;
}
@media (min-width: 840px) {
  .split {
    grid-template-columns: 1.02fr 0.98fr;
  }
  .split--flip .split-media {
    order: -1;
  }
}

/* ---- Figure wrapper for diagrams and mockups ------------------------- */
.figure {
  margin: 0;
}
.figure-media {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: clamp(0.9rem, 2.6vw, 1.5rem);
  background: linear-gradient(180deg, rgba(22, 40, 49, 0.55), rgba(16, 32, 42, 0.35));
  border: 1px solid var(--line);
  border-radius: 22px;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  /* Only diagrams live in .figure-media, and they carry a lot of small labels.
     Below their min-width the strip scrolls (like the tab row) so the text stays
     legible on a phone instead of shrinking to nothing; on desktop it just
     fits. Phone mockups sit in .split-media, not here, so they are untouched. */
  overflow-x: auto;
  scrollbar-width: none;
  justify-content: safe center;
}
.figure-media::-webkit-scrollbar {
  display: none;
}
.figure-media svg {
  width: 100%;
  min-width: 560px;
  height: auto;
  display: block;
  flex: none;
}
.figure-cap {
  margin-top: 0.75rem;
  color: var(--faint);
  font-family: var(--sans);
  font-size: 0.86rem;
  line-height: 1.4;
}
.figure-cap b {
  color: var(--mist);
  font-weight: 600;
}

/* ---- Phone mockup: the real app is a warm CREAM theme, so the screen
        carries the app's own palette (its accent grammar is load-bearing:
        teal = local/private, amber = cloud/spend, gold = ratings). A dark
        bezel lifts it off the Nightshore page. ------------------------- */
.phone {
  width: 100%;
  max-width: 290px;
  margin: 0 auto;
  background: #0a181e;
  border: 1px solid var(--line);
  border-radius: 42px;
  padding: 11px;
  box-shadow:
    0 24px 60px -24px rgba(0, 0, 0, 0.7),
    0 0 0 1px rgba(91, 182, 203, 0.06),
    0 10px 40px -18px rgba(91, 182, 203, 0.22);
}
.phone-screen {
  --a-bg: #f6f4ef;
  --a-raised: #fcfbf7;
  --a-surface: #edeae0;
  --a-border: #e5e0d3;
  --a-ink: #1c2a33;
  --a-soft: #55636b;
  --a-muted: #8a949a;
  --a-teal: #2f5a66;
  --a-teal-deep: #24454f;
  --a-wave: #4b90a3;
  --a-cloud: #a35f0a;
  --a-cloud-br: #e0902f;
  --a-gold: #c98a1f;
  --a-flow: #8aa0a8;
  --a-ok: #2f8f4e;
  position: relative;
  border-radius: 32px;
  overflow: hidden;
  background: var(--a-bg);
  color: var(--a-ink);
  font-family: var(--sans);
  aspect-ratio: 293 / 620;
  display: flex;
  flex-direction: column;
}
.phone-statusbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 9px 20px 2px;
  font-size: 10px;
  font-weight: 700;
  color: var(--a-ink);
}
.phone-statusbar .dots {
  letter-spacing: 1px;
  opacity: 0.75;
}
.app-topbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px 2px;
}
.app-back {
  color: var(--a-wave);
  font-weight: 700;
  font-size: 12px;
}
.app-topbar .grow {
  flex: 1;
}
.app-h1 {
  font-family: var(--serif);
  font-weight: 520;
  font-size: 19px;
  letter-spacing: -0.01em;
  line-height: 1.08;
  color: var(--a-ink);
  padding: 4px 14px 0;
}
.app-lead {
  color: var(--a-soft);
  font-size: 11px;
  line-height: 1.35;
  padding: 3px 14px 0;
}
.app-body {
  flex: 1;
  overflow: hidden;
  padding: 10px 14px 14px;
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.app-card {
  background: var(--a-raised);
  border: 1px solid var(--a-border);
  border-radius: 14px;
  padding: 9px 11px;
}
.app-card--edge-local {
  box-shadow: inset 3px 0 0 var(--a-teal);
}
.app-card--edge-cloud {
  box-shadow: inset 3px 0 0 var(--a-cloud-br);
}
.app-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.app-row .grow {
  flex: 1;
  min-width: 0;
}
.app-title {
  font-weight: 700;
  font-size: 12.5px;
  color: var(--a-ink);
}
.app-sub {
  font-size: 10.5px;
  color: var(--a-soft);
  line-height: 1.3;
}
.app-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 9.5px;
  font-weight: 700;
  padding: 3px 8px;
  border-radius: 999px;
  white-space: nowrap;
}
.app-pill--local {
  color: var(--a-teal-deep);
  background: rgba(47, 90, 102, 0.13);
}
.app-pill--cloud {
  color: #8a5300;
  background: rgba(163, 95, 10, 0.15);
}
.app-pill--ok {
  color: var(--a-ok);
  background: rgba(47, 143, 78, 0.15);
}
.app-pill--anchor {
  color: var(--a-teal-deep);
  background: rgba(47, 90, 102, 0.13);
  border: 1px solid rgba(47, 90, 102, 0.35);
}
.app-dot {
  width: 8px;
  height: 8px;
  border-radius: 999px;
  flex: none;
}
.app-dot--local { background: var(--a-teal); }
.app-dot--cloud { background: var(--a-cloud-br); }
.app-dot--ok { background: var(--a-ok); }
.app-chiprail {
  display: flex;
  gap: 6px;
  overflow: hidden;
}
.app-chip {
  font-size: 10px;
  font-weight: 600;
  padding: 5px 10px;
  border-radius: 999px;
  background: var(--a-surface);
  color: var(--a-soft);
  border: 1px solid var(--a-border);
  white-space: nowrap;
  flex: none;
}
.app-chip--on {
  background: rgba(47, 90, 102, 0.12);
  color: var(--a-teal-deep);
  border-color: rgba(47, 90, 102, 0.3);
}
.app-search {
  display: flex;
  align-items: center;
  gap: 7px;
  background: #fff;
  border: 1px solid var(--a-border);
  border-radius: 11px;
  padding: 8px 11px;
  color: var(--a-muted);
  font-size: 12px;
}
.app-btn {
  background: var(--a-teal);
  color: var(--a-bg);
  font-weight: 700;
  font-size: 10.5px;
  padding: 6px 12px;
  border-radius: 999px;
  white-space: nowrap;
  flex: none;
}
.app-btn--ghost {
  background: transparent;
  color: var(--a-teal-deep);
  border: 1px solid var(--a-border);
}
.app-stars {
  color: var(--a-gold);
  font-size: 11px;
  letter-spacing: 1px;
}
.app-meter {
  height: 5px;
  border-radius: 999px;
  background: var(--a-surface);
  overflow: hidden;
}
.app-meter > i {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--a-flow);
}
.app-field {
  background: #fff;
  border: 1px solid var(--a-border);
  border-radius: 9px;
  padding: 7px 9px;
  font-size: 10.5px;
  color: var(--a-soft);
}
.app-field b {
  color: var(--a-muted);
  font-weight: 500;
}
.app-mono {
  font-family: var(--mono, ui-monospace, "SFMono-Regular", Menlo, monospace);
  font-size: 10px;
}
.app-sheet {
  margin-top: auto;
  background: var(--a-raised);
  border: 1px solid var(--a-border);
  border-top-left-radius: 18px;
  border-top-right-radius: 18px;
  padding: 11px 12px 13px;
  display: flex;
  flex-direction: column;
  gap: 7px;
  box-shadow: 0 -10px 24px -14px rgba(28, 42, 51, 0.25);
}
.app-grab {
  width: 34px;
  height: 4px;
  border-radius: 999px;
  background: var(--a-border);
  margin: 0 auto 3px;
}

/* Two mockups or a mockup beside a diagram, side by side on wide screens. */
.mock-duo {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1.1rem, 3vw, 1.8rem);
}
@media (min-width: 720px) {
  .mock-duo {
    grid-template-columns: 1fr 1fr;
    align-items: start;
  }
}

/* Ethics: a three-signal quick-scan above the detailed tier cards. Colors
   mirror the app's own ethics grammar (red refused, amber gated, green left
   alone), so the site and the product read the same. */
.signals {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
  margin-top: 1.2rem;
}
@media (min-width: 720px) {
  .signals {
    grid-template-columns: repeat(3, 1fr);
  }
}
.signal {
  background: var(--surface);
  border: 1px solid var(--line);
  border-top: 3px solid var(--sig, var(--wave));
  border-radius: 16px;
  padding: 1rem 1.05rem;
}
.signal-head {
  display: flex;
  align-items: center;
  gap: 8px;
}
.signal-dot {
  width: 10px;
  height: 10px;
  border-radius: 999px;
  background: var(--sig, var(--wave));
  flex: none;
}
.signal-name {
  font-family: var(--sans);
  font-weight: 700;
  font-size: 0.98rem;
  color: var(--paper);
}
.signal-body {
  margin-top: 0.5rem;
  color: var(--mist);
  font-size: 0.9rem;
  line-height: 1.42;
}
.signal--refuse { --sig: #e5675a; }
.signal--gate { --sig: #e0902f; }
.signal--allow { --sig: #4fbf7f; }

/* ==== Phone fit and feel ===============================================
   Scoped to narrow screens (the base stylesheet's own phone breakpoint) so
   desktop is untouched. Goals: reach content sooner, make the two scrolling
   strips (tabs, diagrams) read as swipeable instead of cut off, and keep the
   floating email button off the words. */
@media (max-width: 34rem) {
  /* Compact lockup: smaller tile and wordmark, tighter stack, less top air. */
  .sitenav--oscode {
    padding-top: 12px;
  }
  .brand--oscode {
    gap: 2px;
    margin-bottom: 10px;
  }
  .brand--oscode .brand-mark {
    width: 40px;
    height: 40px;
    border-radius: 10px;
  }
  .brand--oscode .brand-word {
    font-size: 1.3rem;
  }
  .brand-sub {
    font-size: 0.68rem;
  }

  /* Tab strip: a plain static horizontal scroll. Smaller type and tighter gaps
     so as many tabs as possible show at once; no snap, no auto-scroll, no fade,
     so the row never moves on its own. It just sits there and scrolls if the
     labels run past the edge. */
  .sitenav--oscode .sitenav-tabs {
    gap: 13px;
  }
  .sitenav--oscode .sitenav-tab {
    font-size: 0.72rem;
    letter-spacing: 0;
    padding-bottom: 11px;
  }

  /* Hero pair: two equal pills that fill the row, so neither wraps alone and
     leaves an uneven stack. On a very narrow phone they drop to two full-width
     rows, which is the same clean shape. */
  .hero-actions .block-cta,
  .hero-actions .hero-cta-ghost {
    flex: 1 1 0;
    min-width: 140px;
    gap: 0.35em;
    padding-inline: 18px;
  }

  /* Diagrams scroll inside their frame on a phone; fade the right edge so the
     cut-off reads as "swipe", not "broken". */
  .figure-media {
    position: relative;
  }
  .figure-media::after {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 44px;
    border-radius: 0 22px 22px 0;
    background: linear-gradient(to right, rgba(11, 20, 23, 0), rgba(11, 20, 23, 0.82));
    pointer-events: none;
  }

  /* Email button: a hair smaller (still a 44px target) and give the page
     bottom clearance so the footer never sits under it. */
  .consult-fab {
    padding: 13px;
  }
  .page--oscode {
    padding-bottom: calc(clamp(48px, 8vw, 88px) + 56px);
  }
}

/* A quiet inline note used for honest limits and footnotes. */
.honest-note {
  margin-top: 1rem;
  padding: 0.85rem 1rem;
  border-left: 2px solid var(--wave-2);
  background: rgba(47, 90, 102, 0.12);
  border-radius: 0 10px 10px 0;
  color: var(--mist);
  font-size: 0.92rem;
  line-height: 1.45;
}
