/* ============================================================================
   Cobia marketing site — Sea Fog design system
   Tokens mirror ios/Cobia/Config/Theme.swift (Sea Fog light appearance).
   Barlow Condensed is reserved for the COBIA. wordmark and nothing else.
   ========================================================================= */

@font-face {
  font-family: 'Barlow Condensed';
  src: url('/fonts/barlow-condensed-700.woff2') format('woff2');
  font-weight: 700;
  font-display: swap;
}
@font-face {
  font-family: 'Inter Tight';
  src: url('/fonts/inter-tight-var.woff2') format('woff2-variations');
  font-weight: 400 700;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter-var.woff2') format('woff2-variations');
  font-weight: 400 700;
  font-display: swap;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url('/fonts/jetbrains-mono-var.woff2') format('woff2-variations');
  font-weight: 400 700;
  font-display: swap;
}

:root {
  /* Sea Fog surfaces */
  --bg: #EAF0F6;
  --surface: #FFFFFF;
  --surface-alt: #F4F7FA;
  --surface-inset: #F1F5F9;
  --border: #E2E8F0;
  --border-soft: #EEF2F6;

  /* Deep Water — used sparingly for contrast bands */
  --deep: #0A1628;
  --deep-2: #111D33;
  --deep-border: #1C2E4A;

  /* Ink ramp */
  --ink: #16233A;
  --ink-2: #44546C;
  --ink-3: #5E6B82;   /* deeper than the app token: page bg is #EAF0F6, not white */
  --ink-4: #8A97AC;

  /* Accents */
  --teal: #00846C;
  --teal-strong: #00735E;   /* small text on the page background */
  --teal-graphic: #009878;
  --teal-bright: #00D4AA;
  --gold: #96690A;
  --gold-strong: #855A08;
  --gold-graphic: #D99A10;
  --copper: #A6591F;
  --copper-strong: #944E1A;
  --blue: #256B9D;
  --blue-graphic: #2E7FB8;
  --purple: #7434D6;
  --green: #0D7F4D;
  --red: #D93636;

  /* Type */
  --display: 'Inter Tight', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;
  --wordmark: 'Barlow Condensed', 'Inter Tight', sans-serif;

  /* Layout */
  --max: 1320px;          /* ONE page rail. .wrap and .wrap-wide are identical
                             so hero and body sections never disagree. */
  --gutter: clamp(1.25rem, 4vw, 2.5rem);
  --r-sm: 10px;
  --r: 16px;
  --r-lg: 24px;
  --r-xl: 32px;

  /* Elevation — Sea Fog whisper shadows */
  --sh-1: 0 1px 3px rgba(22, 35, 58, 0.05);
  --sh-2: 0 4px 16px rgba(22, 35, 58, 0.06), 0 1px 3px rgba(22, 35, 58, 0.04);
  --sh-3: 0 18px 48px rgba(22, 35, 58, 0.10), 0 4px 12px rgba(22, 35, 58, 0.05);
  --sh-4: 0 40px 90px rgba(10, 22, 40, 0.18), 0 10px 30px rgba(10, 22, 40, 0.08);

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-io: cubic-bezier(0.65, 0, 0.35, 1);
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  color-scheme: light;

  /* The page should move on one axis and nothing else, the way an app screen
   * does. `manipulation` keeps ordinary panning, including the sideways scroll
   * inside .table-scroll, and drops double tap to zoom, which was the easiest
   * way to knock the layout to 3x by mistiming a tap on a link.
   *
   * touch-action is not inherited, but the effective behaviour for a touch is
   * the intersection of the touched element and its ancestors, so setting it
   * on the root covers the whole document. */
  touch-action: manipulation;

  /* No rubber band at the ends of the document and no pull to refresh. */
  overscroll-behavior: none;
}

/* Stop the page panning sideways on a phone.
 *
 * `overflow-x: hidden` was already on body and did nothing, because the
 * viewport scrolls on the root element: body clipped its own children while
 * html happily kept scrolling. The hero phone cluster fans two phones past the
 * edge on purpose, so on a 375px screen the document was 405px wide and the
 * whole canvas could be dragged around.
 *
 * `clip` rather than `hidden` on purpose. `hidden` makes the element a scroll
 * container, which silently kills `position: sticky` on every descendant — and
 * this site sticks the header, the showcase phone, the guide table of contents
 * and .split-pin media. `clip` does not create a scroll container, so sticky
 * keeps working.
 *
 * The root rule alone was not enough. Clipping on the root has to reach the
 * viewport through overflow propagation, and WebKit does not carry `clip`
 * across that step, so iPhones kept scrolling sideways while every desktop
 * browser looked fixed. `main` clips as a plain element, which needs no
 * propagation and is where the only real overflow on the site lives, so the
 * lock no longer depends on a root-to-viewport behaviour to hold. The root
 * rule stays as the backstop for anything outside `main`. */
html, body { overflow-x: clip; }
main { overflow-x: clip; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* Scroll lock behind the open mobile menu.
 *
 * `body { overflow: hidden }` used to do this from app.js and stopped working
 * the day the root started clipping: overflow propagates to the viewport from
 * the root element, and once html is not `visible` the body value is no longer
 * consulted, so the page scrolled away underneath the menu. Taking body out of
 * flow is the one lock iOS Safari has always honoured. app.js holds the scroll
 * offset in `top` and puts it back on close.
 *
 * No `overflow: hidden` alongside it. That turns body into a scroll container,
 * and the sticky header then sticks to body's own scrollport rather than the
 * viewport, which parks it a full scroll offset above the screen and takes the
 * menu button with it. Body is out of flow, so it adds nothing to the root's
 * scrollable area either way, and the menu sheet covers what spills. */
body.nav-open {
  position: fixed;
  left: 0;
  right: 0;
  width: 100%;
}

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--body);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-feature-settings: 'cv11', 'ss01';
}

img, svg, video { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }

::selection { background: rgba(0, 132, 108, 0.16); color: var(--ink); }
/* Selection has to be restated per surface, because the rule above is tuned
   for the pale canvas and inverts badly on Deep Water: a 16% wash is too
   faint to register against #0A1628, and `--ink` is DARKER than the
   background it lands on, so selecting dark-band text hides it instead of
   highlighting it. Dark surfaces get a wash heavy enough to read plus light
   text. `::selection` does not inherit, so each dark surface needs its own
   rule rather than relying on the cascade. */
.band-deep ::selection,
.band-deep::selection,
.site-footer ::selection,
.site-footer::selection { background: rgba(0, 212, 170, 0.30); color: #fff; }

/* ── Typography ───────────────────────────────────────────────────────── */

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 600;
  letter-spacing: -0.022em;
  line-height: 1.08;
  color: var(--ink);
  text-wrap: balance;
}

.h-display { font-size: max(2.35rem, min(clamp(2.35rem, 5.2vw, 3.9rem), 9.5vh)); font-weight: 700; letter-spacing: -0.035em; line-height: 1.04; }
.h1 { font-size: max(1.95rem, min(clamp(1.95rem, 4vw, 2.9rem), 7.5vh)); font-weight: 700; letter-spacing: -0.03em; }
.h2 { font-size: clamp(1.6rem, 2.9vw, 2.2rem); font-weight: 650; letter-spacing: -0.026em; }
.h3 { font-size: clamp(1.2rem, 2vw, 1.5rem); font-weight: 600; letter-spacing: -0.018em; line-height: 1.25; }
.h4 { font-size: 1.0625rem; font-weight: 600; letter-spacing: -0.012em; line-height: 1.35; }

.lede { font-size: clamp(1.0313rem, 1.15vw, 1.1563rem); color: var(--ink-2); line-height: 1.55; text-wrap: pretty; }
.body { color: var(--ink-2); text-wrap: pretty; }
.small { font-size: 0.9375rem; color: var(--ink-3); }
.tiny { font-size: 0.8125rem; color: var(--ink-3); }

.eyebrow {
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--teal-strong);
}
.eyebrow.gold { color: var(--gold-strong); }
.eyebrow.blue { color: var(--blue); }
.eyebrow.copper { color: var(--copper-strong); }
.eyebrow.purple { color: var(--purple); }

.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.tint { color: var(--teal); }
.muted { color: var(--ink-3); }

/* ── Wordmark (the only Barlow on the site) ───────────────────────────── */

.wordmark {
  font-family: var(--wordmark);
  font-weight: 700;
  letter-spacing: 0.11em;
  line-height: 1;
  display: inline-flex;
  align-items: baseline;
  user-select: none;
}
.wordmark .dot { color: var(--teal-graphic); }

/* ── Layout primitives ────────────────────────────────────────────────── */

.wrap { width: 100%; max-width: var(--max); margin-inline: auto; padding-inline: var(--gutter); }
.wrap-wide { max-width: var(--max); }   /* kept as an alias; same rail as .wrap */
.wrap-narrow { max-width: 780px; }      /* centred reading column, intentional */

section { position: relative; }
.section { padding-block: clamp(3.25rem, 6vw, 5.5rem); }
.section-sm { padding-block: clamp(2.25rem, 4vw, 3.5rem); }

.stack > * + * { margin-top: 1rem; }
.stack-sm > * + * { margin-top: 0.5rem; }
.stack-lg > * + * { margin-top: 1.75rem; }

.grid { display: grid; gap: clamp(1rem, 2vw, 1.5rem); }
.g2 { grid-template-columns: repeat(2, 1fr); }
.g3 { grid-template-columns: repeat(3, 1fr); }
.g4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) { .g3, .g4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .g2, .g3, .g4 { grid-template-columns: 1fr; } }

.center { text-align: center; }
.section-head { max-width: 720px; margin-inline: auto; text-align: center; margin-bottom: clamp(1.9rem, 3.4vw, 2.9rem); }
.section-head .lede { margin-top: 1rem; }
.section-head.left { margin-inline: 0; text-align: left; }

/* ── Header ───────────────────────────────────────────────────────────── */

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  background: rgba(234, 240, 246, 0.72);
  border-bottom: 1px solid transparent;
  transition: background 0.3s var(--ease), border-color 0.3s var(--ease);
}
.site-header.scrolled { background: rgba(234, 240, 246, 0.88); border-bottom-color: var(--border); }

.nav { display: flex; align-items: center; gap: 1.5rem; height: 68px; }
.nav-logo { font-size: 1.5rem; margin-right: auto; }
.nav-links { display: flex; align-items: center; gap: 0.25rem; }
.nav-links a {
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--ink-2);
  padding: 0.5rem 0.75rem;
  border-radius: 9px;
  transition: color 0.18s, background 0.18s;
}
.nav-links a:hover { color: var(--ink); background: rgba(22, 35, 58, 0.045); }
.nav-links a[aria-current] { color: var(--teal-strong); }

.nav-drop { position: relative; }
.nav-drop > button {
  font-size: 0.9375rem; font-weight: 500; color: var(--ink-2);
  padding: 0.5rem 0.75rem; border-radius: 9px;
  display: inline-flex; align-items: center; gap: 0.3rem;
  transition: color 0.18s, background 0.18s;
}
.nav-drop > button:hover, .nav-drop[data-open] > button { color: var(--ink); background: rgba(22, 35, 58, 0.045); }
.nav-drop > button svg { width: 12px; transition: transform 0.24s var(--ease); }
.nav-drop[data-open] > button svg { transform: rotate(180deg); }

.nav-panel {
  position: absolute;
  top: calc(100% + 10px);
  left: 50%;
  translate: -50% 0;
  width: min(660px, 88vw);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-3);
  padding: 1rem;
  display: block;          /* .nav-panel-grid owns the two column layout */
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity 0.22s var(--ease), transform 0.22s var(--ease), visibility 0.22s;
}
.nav-drop[data-open] .nav-panel { opacity: 1; visibility: visible; transform: translateY(0); }
.nav-panel-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.15rem; }
.nav-panel a {
  display: flex; align-items: flex-start; gap: 0.7rem;
  padding: 0.6rem 0.7rem; border-radius: 11px;
  transition: background 0.16s;
}
.nav-panel a:hover { background: var(--surface-alt); }
.nav-copy { display: block; min-width: 0; }
.nav-panel strong { display: block; font-size: 0.9375rem; font-weight: 600; color: var(--ink); letter-spacing: -0.01em; }
.nav-panel .nav-copy > span { display: block; font-size: 0.8125rem; color: var(--ink-3); line-height: 1.4; margin-top: 1px; }

.nav-panel-more {
  display: flex; align-items: center; justify-content: center; gap: 0.4rem;
  margin-top: 0.5rem; padding-top: 0.85rem;
  border-top: 1px solid var(--border-soft);
  font-size: 0.875rem; font-weight: 600; color: var(--teal);
}
.nav-panel-more:hover { background: transparent; color: #006E59; }
.nav-panel-more svg { width: 14px; transition: transform 0.24s var(--ease); }
.nav-panel-more:hover svg { transform: translateX(3px); }

/* Menu row glyph. Same tone vocabulary as the card icon badges. */
.nav-ic { width: 32px; height: 32px; border-radius: 9px; margin-top: 1px; }
.nav-ic svg { width: 16px; height: 16px; }
.mobile-nav .nav-ic { width: 26px; height: 26px; border-radius: 7px; margin: 0; }
.mobile-nav .nav-ic svg { width: 14px; height: 14px; }

.nav-toggle { display: none; width: 40px; height: 40px; border-radius: 10px; align-items: center; justify-content: center; }
.nav-toggle span { display: block; width: 18px; height: 1.5px; background: var(--ink); position: relative; transition: background 0.2s; }
.nav-toggle span::before, .nav-toggle span::after {
  content: ''; position: absolute; left: 0; width: 18px; height: 1.5px; background: var(--ink);
  transition: transform 0.28s var(--ease);
}
.nav-toggle span::before { top: -5.5px; }
.nav-toggle span::after { top: 5.5px; }
body.nav-open .nav-toggle span { background: transparent; }
body.nav-open .nav-toggle span::before { transform: translateY(5.5px) rotate(45deg); }
body.nav-open .nav-toggle span::after { transform: translateY(-5.5px) rotate(-45deg); }

@media (max-width: 940px) {
  .nav-links, .nav > .btn { display: none; }
  .nav-toggle { display: flex; }
  .nav-logo { margin-right: auto; }
}

.mobile-nav {
  position: fixed; inset: 68px 0 0; z-index: 99;
  background: var(--bg);
  padding: 1.5rem var(--gutter) 3rem;
  overflow-y: auto;
  overscroll-behavior: contain;
  opacity: 0; visibility: hidden; transform: translateY(-8px);
  transition: opacity 0.25s var(--ease), transform 0.25s var(--ease), visibility 0.25s;
}
body.nav-open .mobile-nav { opacity: 1; visibility: visible; transform: none; }
.mobile-nav h4 { font-size: 0.6875rem; font-family: var(--mono); letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-4); margin: 1.75rem 0 0.5rem; }
.mobile-nav h4:first-child { margin-top: 0; }
.mobile-nav a { display: flex; align-items: center; gap: 0.7rem; padding: 0.6rem 0; font-size: 1.0625rem; font-weight: 500; border-bottom: 1px solid var(--border-soft); }

/* ── Buttons ──────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.55rem;
  padding: 0.8rem 1.4rem;
  border-radius: 999px;
  font-size: 0.9375rem; font-weight: 600; letter-spacing: -0.008em;
  white-space: nowrap;
  transition: transform 0.22s var(--ease), box-shadow 0.22s var(--ease), background 0.2s, color 0.2s, border-color 0.2s;
  will-change: transform;
}
.btn svg { width: 17px; height: 17px; flex: none; fill: currentColor; }

.btn-primary { background: var(--teal); color: #fff; box-shadow: 0 1px 2px rgba(0, 74, 60, 0.2), 0 6px 20px rgba(0, 132, 108, 0.22); }
.btn-primary:hover { background: #006E59; transform: translateY(-2px); box-shadow: 0 2px 4px rgba(0, 74, 60, 0.22), 0 12px 30px rgba(0, 132, 108, 0.3); }
.btn-primary:active { transform: translateY(0); }

.btn-ghost { background: var(--surface); color: var(--ink); border: 1px solid var(--border); box-shadow: var(--sh-1); }
.btn-ghost:hover { border-color: #CBD7E4; transform: translateY(-2px); box-shadow: var(--sh-2); }

.btn-quiet { color: var(--ink-2); padding-inline: 0.9rem; }
.btn-quiet:hover { color: var(--teal); }

.btn-lg { padding: 1rem 1.75rem; font-size: 1rem; }
.btn-dark { background: var(--ink); color: #fff; }
.btn-dark:hover { background: #0A1628; transform: translateY(-2px); box-shadow: var(--sh-3); }

.btn-row { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center; }
.btn-row.center { justify-content: center; }

/* App Store badge + Android coming-soon chip.
   The badge <img> is Apple's own artwork and must not be tinted, shadowed,
   rotated or otherwise restyled. Only the wrapper gets hover motion, and the
   row gap provides Apple's required clear space (>= 1/4 of badge height). */
.store-row { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center; }
.store-row.center { justify-content: center; }

/* Region note under the store badge. Copper rather than red: this is a fact
   about where the app has shipped, not an error the reader caused. */
.store-geo {
  margin-top: 0.7rem;
  font-size: 0.875rem;
  line-height: 1.45;
  color: var(--copper-strong);
  max-width: 42ch;
}
.store-row.center + .store-geo { margin-inline: auto; text-align: center; }
.store-geo[hidden] { display: none; }

.store-badge {
  display: inline-block;
  border-radius: 9px;
  transition: transform 0.24s var(--ease);
}
.store-badge:hover { transform: translateY(-2px); }
.store-badge img { height: 44px; width: auto; }   /* Apple minimum is 40px */

.soon-chip {
  display: inline-flex; align-items: center; gap: 0.5rem;
  height: 44px; padding: 0 1.15rem;
  border-radius: 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--sh-1);
  font-size: 0.9375rem; font-weight: 500; color: var(--ink-2);
  white-space: nowrap;
}
.soon-chip svg {
  width: 15px; height: 15px; flex: none;
  stroke: var(--ink-3); fill: none;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}
.band-deep .soon-chip { background: rgba(255,255,255,0.06); border-color: rgba(255,255,255,0.16); color: #A0B0C4; box-shadow: none; }
.band-deep .soon-chip svg { stroke: #8494AD; }
.site-footer .soon-chip { background: rgba(255,255,255,0.05); border-color: rgba(255,255,255,0.14); color: #8494AD; box-shadow: none; }

/* ── Cards ────────────────────────────────────────────────────────────── */

.card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: clamp(1.35rem, 2.4vw, 1.9rem);
  box-shadow: var(--sh-1);
  transition: transform 0.32s var(--ease), box-shadow 0.32s var(--ease), border-color 0.32s var(--ease);
  overflow: hidden;
  /* Column flex so a card's call to action can be pushed to the bottom
     regardless of how long the body copy above it runs. Without this, a row
     of cards puts its links at four different heights and the eye reads the
     ragged line before it reads any of them. */
  display: flex;
  flex-direction: column;
  height: 100%;
}
.card-link:hover { transform: translateY(-4px); border-color: #D3DFEC; box-shadow: var(--sh-3); }

/* cursor spotlight */
.card-spot::before {
  content: '';
  position: absolute; inset: -1px;
  border-radius: inherit;
  background: radial-gradient(340px circle at var(--mx, 50%) var(--my, 0%), rgba(0, 152, 120, 0.09), transparent 62%);
  opacity: 0; transition: opacity 0.35s var(--ease); pointer-events: none;
}
.card-spot:hover::before { opacity: 1; }

.card > * { position: relative; }

.icon-badge, .nav-ic {
  display: grid; place-items: center; flex: none;
  background: var(--tone-bg, rgba(0, 132, 108, 0.09));
  color: var(--tone-fg, var(--teal));
}
.icon-badge { width: 42px; height: 42px; border-radius: 12px; margin-bottom: 1.1rem; }
.icon-badge svg, .nav-ic svg { stroke: currentColor; fill: none; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.icon-badge svg { width: 21px; height: 21px; }

.icon-badge.gold,   .nav-ic.gold   { --tone-bg: rgba(150, 105, 10, 0.10); --tone-fg: var(--gold); }
.icon-badge.blue,   .nav-ic.blue   { --tone-bg: rgba(37, 107, 157, 0.09); --tone-fg: var(--blue); }
.icon-badge.copper, .nav-ic.copper { --tone-bg: rgba(166, 89, 31, 0.09);  --tone-fg: var(--copper); }
.icon-badge.purple, .nav-ic.purple { --tone-bg: rgba(116, 52, 214, 0.08); --tone-fg: var(--purple); }
.icon-badge.green,  .nav-ic.green  { --tone-bg: rgba(13, 127, 77, 0.09);  --tone-fg: var(--green); }

.card h3 { margin-bottom: 0.5rem; }
.card p { color: var(--ink-2); font-size: 0.9688rem; line-height: 1.55; }

/* margin-top:auto is what does the anchoring. `align-self` keeps the flex
   stretch from widening the link's hit area across the whole card. */
.card-arrow {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  gap: 0.35rem;
  margin-top: auto;
  padding-top: 1rem;
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--teal);
}
.card-arrow svg { width: 15px; transition: transform 0.28s var(--ease); stroke: currentColor; fill: none; stroke-width: 2; }
.card-link:hover .card-arrow svg { transform: translateX(4px); }

/* ── Pills, chips, badges ─────────────────────────────────────────────── */

.pill {
  display: inline-flex; align-items: center; gap: 0.45rem;
  padding: 0.4rem 0.85rem;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--border);
  font-size: 0.8125rem; font-weight: 500; color: var(--ink-2);
  box-shadow: var(--sh-1);
  white-space: nowrap;
}
.pill .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--teal-graphic); flex: none; }

.tag-auth, .tag-import {
  display: inline-flex; align-items: center; gap: 0.35rem;
  padding: 0.3rem 0.7rem; border-radius: 999px;
  font-size: 0.75rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  font-family: var(--mono);
}
.tag-auth { background: rgba(13, 127, 77, 0.1); color: var(--green); }
.tag-import { background: rgba(166, 89, 31, 0.1); color: var(--copper); }

/* ── Stats ────────────────────────────────────────────────────────────── */

.stat-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: var(--r); overflow: hidden; }
@media (max-width: 720px) { .stat-row { grid-template-columns: repeat(2, 1fr); } }
.stat { background: var(--surface); padding: 1.4rem 1.25rem; }
.stat b { display: block; font-family: var(--display); font-size: clamp(1.7rem, 3.2vw, 2.3rem); font-weight: 700; letter-spacing: -0.03em; color: var(--ink); line-height: 1; font-variant-numeric: tabular-nums; }
.stat span { display: block; font-size: 0.8125rem; color: var(--ink-3); margin-top: 0.45rem; letter-spacing: 0.01em; }

/* ── Phone frame ──────────────────────────────────────────────────────── */

.phone {
  position: relative;
  width: 100%;
  max-width: 300px;
  /* No aspect-ratio here on purpose. The ratio lives on the <img> so the image
     box matches the screenshot exactly and object-fit never crops. The frame
     height is then image + padding, which makes the bezel a uniform border. */
  border-radius: 13.5% / 6.2%;
  background: linear-gradient(158deg, #2B3A4E 0%, #0F1A2B 42%, #26374B 100%);
  padding: 1.6%;
  box-shadow: var(--sh-4);
  margin-inline: auto;
}
.phone::after {
  content: '';
  position: absolute; inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14);
  pointer-events: none;
}
.phone img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1206 / 2622;   /* the raw simulator capture ratio */
  object-fit: cover;           /* a no-op now that the box matches the source */
  border-radius: 12.4% / 5.6%;
  background: var(--bg);
}
.phone-lg { max-width: 340px; }
.phone-sm { max-width: 250px; }

/* A photograph rather than a screenshot. Deliberately not a phone frame, so
   the eye reads it as the thing that happened rather than another screen. The
   aspect-ratio matches the source so it never shifts while loading. */
.photo-card {
  position: relative;
  width: 100%;
  max-width: 300px;
  margin-inline: auto;
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--sh-4);
}
.photo-card img { display: block; width: 100%; height: auto; aspect-ratio: 1050 / 1400; object-fit: cover; }
.photo-card::after {
  content: '';
  position: absolute; inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(15, 26, 43, 0.09);
  pointer-events: none;
}

/* Photograph, arrow, screen. Sits inside a split's media column, so it has to
   stay narrow. Stacks below the split breakpoint, where the arrow turns down. */
.flow-pair {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: clamp(0.6rem, 1.6vw, 1.1rem);
  width: 100%;
}
@media (max-width: 900px) {
  .flow-pair { grid-template-columns: 1fr; justify-items: center; gap: 1.1rem; }
  .flow-pair .photo-card, .flow-pair .phone { max-width: 240px; }
}

/* The in-between beat on a paired photo and screen. Rotates to point down the
   column once the pair stacks, because an arrow aiming right at a thing that
   is now below it is worse than no arrow. */
.flow-arrow {
  display: grid;
  place-items: center;
  color: var(--ink-3);
}
.flow-arrow svg { width: 30px; height: 30px; stroke: currentColor; fill: none; stroke-width: 1.6; }
@media (max-width: 900px) { .flow-arrow svg { transform: rotate(90deg); } }

/* A captioned screenshot, for the rare case where two shots have to be read
   against each other and the caption is what makes the pair legible. */
.shot-fig { margin: 0; display: flex; flex-direction: column; gap: 1rem; }
.shot-fig figcaption { text-align: center; max-width: 30ch; margin-inline: auto; }
.shot-fig figcaption strong {
  display: block;
  font-family: var(--display);
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: -0.012em;
  color: var(--ink);
}
.shot-fig figcaption span { display: block; font-size: 0.9375rem; color: var(--ink-2); margin-top: 2px; }

/* A screen recording sits in the same box as a screenshot, so the two are
   interchangeable inside split() and never shift the layout between them. */
.phone video {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1206 / 2622;
  object-fit: cover;
  border-radius: 12.4% / 5.6%;
  background: var(--bg);
}

/* ── Hero ─────────────────────────────────────────────────────────────── */

/* No overflow clip on the hero itself. It used to clip the decorative glows,
   but it was also slicing the phone cluster's drop shadow off on a hard line
   where the marquee begins. The glows now live in .hero-deco, which does the
   clipping, so the shadow is free to fall away behind the marquee. */
.hero { position: relative; padding-block: clamp(2.25rem, 4vw, 3.5rem) clamp(2.75rem, 5vw, 4.5rem); }
.hero-deco { position: absolute; inset: 0; overflow: hidden; z-index: 0; pointer-events: none; }

.hero-bg { position: absolute; inset: -10% -20% auto; height: 130%; z-index: 0; pointer-events: none; }
.hero-bg canvas { width: 100%; height: 100%; opacity: 0.5; }

.hero-glow {
  position: absolute; z-index: 0; pointer-events: none;
  border-radius: 50%; filter: blur(90px);
}
.hero-glow.a { top: -14%; left: 4%; width: 46vw; height: 46vw; max-width: 640px; max-height: 640px; background: radial-gradient(circle, rgba(0, 212, 170, 0.2), transparent 68%); }
.hero-glow.b { top: 8%; right: -6%; width: 44vw; height: 44vw; max-width: 620px; max-height: 620px; background: radial-gradient(circle, rgba(74, 159, 212, 0.2), transparent 68%); }

.hero .wrap { position: relative; z-index: 2; }

.hero-grid { display: grid; grid-template-columns: 1.05fr 0.95fr; gap: clamp(2rem, 5vw, 4.5rem); align-items: center; }
@media (max-width: 940px) { .hero-grid { grid-template-columns: 1fr; text-align: center; } .hero-grid .btn-row, .hero-grid .store-row, .hero-grid .hero-meta { justify-content: center; } }

.hero h1 { margin-block: 1.25rem; }
.hero .lede { max-width: 34ch; }
@media (max-width: 940px) { .hero .lede { margin-inline: auto; } }

.hero-meta { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1.75rem; }

/* Phone cluster */
.hero-phones { position: relative; display: grid; place-items: center; min-height: min(520px, 56vh); }
.hero-phones .phone { position: absolute; }
.hero-phones .p-main { max-width: 292px; z-index: 3; }
.hero-phones .p-left { max-width: 218px; transform: translate(-64%, 12%) rotate(-7deg); z-index: 2; opacity: 0.96; }
.hero-phones .p-right { max-width: 218px; transform: translate(64%, -10%) rotate(7deg); z-index: 2; opacity: 0.96; }
@media (max-width: 620px) {
  .hero-phones { min-height: 460px; }
  .hero-phones .p-main { max-width: 240px; }
  .hero-phones .p-left { max-width: 160px; transform: translate(-72%, 16%) rotate(-8deg); }
  .hero-phones .p-right { max-width: 160px; transform: translate(72%, -14%) rotate(8deg); }
}

/* ── Word reveal ──────────────────────────────────────────────────────── */

.reveal-words .w { display: inline-block; overflow: hidden; vertical-align: bottom; padding-bottom: 0.14em; margin-bottom: -0.14em; }
.reveal-words .w > .ww { display: inline-block; }
.js .reveal-words .w > .ww {
  transform: translateY(105%);
  transition: transform 0.85s var(--ease);
  transition-delay: calc(var(--i) * 55ms);
}
.js .reveal-words.in .w > .ww { transform: translateY(0); }

/* ── Scroll reveal ────────────────────────────────────────────────────── */

.js [data-r] { opacity: 0; transform: translateY(18px); transition: opacity 0.75s var(--ease), transform 0.75s var(--ease); }
.js [data-r].in { opacity: 1; transform: none; }
.js [data-r-stagger] > * { opacity: 0; transform: translateY(18px); transition: opacity 0.7s var(--ease), transform 0.7s var(--ease); }
.js [data-r-stagger].in > * { opacity: 1; transform: none; }
.js [data-r-stagger].in > *:nth-child(1) { transition-delay: 0ms; }
.js [data-r-stagger].in > *:nth-child(2) { transition-delay: 70ms; }
.js [data-r-stagger].in > *:nth-child(3) { transition-delay: 140ms; }
.js [data-r-stagger].in > *:nth-child(4) { transition-delay: 210ms; }
.js [data-r-stagger].in > *:nth-child(5) { transition-delay: 280ms; }
.js [data-r-stagger].in > *:nth-child(6) { transition-delay: 350ms; }
.js [data-r-stagger].in > *:nth-child(7) { transition-delay: 420ms; }
.js [data-r-stagger].in > *:nth-child(8) { transition-delay: 490ms; }
.js [data-r-stagger].in > *:nth-child(9) { transition-delay: 560ms; }

/* ── Sticky showcase (scroll-linked screenshot swap) ──────────────────── */

.showcase { position: relative; }
.showcase-inner { display: grid; grid-template-columns: 1fr 400px; gap: clamp(2rem, 6vw, 5rem); align-items: start; }
@media (max-width: 940px) { .showcase-inner { grid-template-columns: 1fr; } }

.showcase-steps > * + * { margin-top: clamp(3rem, 12vh, 7rem); }
.showcase-step { transition: opacity 0.45s var(--ease); }
@media (min-width: 941px) { .js .showcase-step { opacity: 0.35; } .showcase-step.active { opacity: 1; } }
.showcase-step .eyebrow { display: block; margin-bottom: 0.75rem; }
.showcase-step h3 { font-size: clamp(1.5rem, 2.6vw, 2rem); margin-bottom: 0.75rem; }

.showcase-sticky { position: sticky; top: 108px; display: grid; place-items: center; }
@media (max-width: 940px) { .showcase-sticky { display: none; } }
.showcase-stage { position: relative; width: 100%; max-width: 320px; }
.js .showcase-stage .phone { position: absolute; inset: 0 0 auto 0; opacity: 0; transition: opacity 0.55s var(--ease), transform 0.7s var(--ease); transform: scale(0.97); max-width: none; }
.showcase-stage .phone.active { opacity: 1; transform: none; }
.showcase-stage .phone:first-child { position: relative; }

/* mobile fallback: inline phone per step */
.showcase-step .phone { display: none; margin-top: 1.75rem; }
@media (max-width: 940px) { .showcase-step .phone { display: block; } }

/* ── Split feature rows ───────────────────────────────────────────────── */

.split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem, 6vw, 5rem); align-items: center; }
@media (max-width: 900px) { .split { grid-template-columns: 1fr; } .split.flip > *:first-child { order: 2; } }
.split-media { display: grid; place-items: center; }

/* Top-aligned split. `.split` centres its two columns, which is right when both
   sides are a block of similar height, and wrong the moment each column opens
   with its own heading: unequal column heights push the two headings to
   different baselines and the section reads as a mistake before it reads as
   anything else. Use this wherever both columns start with a heading. */
.split-top { align-items: start; }

/* Pinned media. The screenshot holds its place while the copy beside it moves,
   the same behaviour as the sticky showcase further up the page.
   Only does anything when the text column is the taller of the two, so it is
   opt-in per block rather than applied to every split. Below the stacking
   breakpoint there is no second column to scroll against, so it is dropped. */
@media (min-width: 901px) {
  .split-pin { align-items: start; }
  .split-pin .split-media { position: sticky; top: 108px; }
}

.checklist { list-style: none; }
.checklist li { position: relative; padding-left: 1.85rem; color: var(--ink-2); }
.checklist li + li { margin-top: 0.7rem; }
.checklist li::before {
  content: ''; position: absolute; left: 0; top: 0.44em;
  width: 17px; height: 17px; border-radius: 50%;
  background: rgba(0, 132, 108, 0.1);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2300846C' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
  background-size: 11px; background-repeat: no-repeat; background-position: center;
}
.checklist li strong { color: var(--ink); font-weight: 600; }

/* ── Deep band ────────────────────────────────────────────────────────── */

.band-deep {
  background: var(--deep);
  color: #fff;
  position: relative;
  overflow: hidden;
}
.band-deep::before {
  content: ''; position: absolute; inset: 0;
  background:
    radial-gradient(700px circle at 18% 8%, rgba(0, 212, 170, 0.15), transparent 62%),
    radial-gradient(620px circle at 86% 92%, rgba(74, 159, 212, 0.14), transparent 60%);
  pointer-events: none;
}
.band-deep .wrap { position: relative; z-index: 1; }
.band-deep h1, .band-deep h2, .band-deep h3, .band-deep h4 { color: #fff; }
.band-deep .lede, .band-deep .body, .band-deep p { color: #A0B0C4; }
.band-deep .small, .band-deep .tiny, .band-deep .muted { color: #8494AD; }
.band-deep .eyebrow { color: var(--teal-bright); }
.band-deep .card { background: var(--deep-2); border-color: var(--deep-border); box-shadow: none; }
.band-deep .card p { color: #A0B0C4; }
.band-deep .card-link:hover { border-color: #2C4068; transform: translateY(-4px); }
.band-deep .icon-badge { --tone-bg: rgba(0, 212, 170, 0.12); --tone-fg: var(--teal-bright); }
.band-deep .stat-row { background: var(--deep-border); border-color: var(--deep-border); }
.band-deep .stat { background: var(--deep-2); }
.band-deep .stat b { color: #fff; }
.band-deep .stat span { color: #8494AD; }
.band-deep .checklist li { color: #A0B0C4; }
.band-deep .checklist li strong { color: #fff; }
.band-deep .checklist li::before {
  background-color: rgba(0, 212, 170, 0.14);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2300D4AA' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
}
.band-deep .btn-ghost { background: rgba(255, 255, 255, 0.06); color: #fff; border-color: rgba(255, 255, 255, 0.16); box-shadow: none; }
.band-deep .btn-ghost:hover { background: rgba(255, 255, 255, 0.1); border-color: rgba(255, 255, 255, 0.28); }
.band-deep .btn-primary { background: var(--teal-bright); color: #021A14; box-shadow: 0 8px 30px rgba(0, 212, 170, 0.28); }
.band-deep .btn-primary:hover { background: #2BE0BC; }
.band-deep .pill { background: rgba(255, 255, 255, 0.05); border-color: rgba(255, 255, 255, 0.13); color: #A0B0C4; box-shadow: none; }
.band-deep .store-badge { background: #fff; color: var(--ink); }
.band-deep .store-badge.soon { background: rgba(255, 255, 255, 0.05); color: #A0B0C4; border-color: rgba(255, 255, 255, 0.15); }
.band-deep .store-badge.soon b { color: #fff; }
.band-deep .quote-mark { color: rgba(0, 212, 170, 0.3); }

.band-alt { background: linear-gradient(180deg, var(--surface-alt) 0%, var(--bg) 100%); }
.band-surface { background: var(--surface); }

/* ── Marquee ──────────────────────────────────────────────────────────── */

.marquee { overflow: hidden; -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); }
.marquee-track { display: flex; gap: 0.75rem; width: max-content; animation: marquee 46s linear infinite; }
.marquee:hover .marquee-track { animation-play-state: paused; }
@keyframes marquee { to { transform: translateX(-50%); } }
.marquee .pill { font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.02em; }
.pill-ic {
  width: 14px; height: 14px; flex: none;
  stroke: var(--teal-graphic); fill: none;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
  opacity: 0.85;
}

/* ── Chat bubble mock ─────────────────────────────────────────────────── */

.chat { display: flex; flex-direction: column; gap: 0.75rem; }
.bubble { max-width: 84%; padding: 0.85rem 1.1rem; border-radius: 18px; font-size: 0.9688rem; line-height: 1.5; }
.bubble.you { align-self: flex-end; background: var(--teal); color: #fff; border-bottom-right-radius: 6px; }
.bubble.ai { align-self: flex-start; background: var(--surface); border: 1px solid var(--border); color: var(--ink-2); border-bottom-left-radius: 6px; box-shadow: var(--sh-1); }
.bubble.ai strong { color: var(--ink); font-weight: 600; }
.band-deep .bubble.ai { background: var(--deep-2); border-color: var(--deep-border); color: #A0B0C4; }
.band-deep .bubble.ai strong { color: #fff; }
.band-deep .bubble.you { background: var(--teal-bright); color: #021A14; }

/* ── FAQ ──────────────────────────────────────────────────────────────── */

.faq-item { border-bottom: 1px solid var(--border); }
.faq-q {
  width: 100%; display: flex; align-items: flex-start; justify-content: space-between; gap: 1.5rem;
  padding: 1.35rem 0; text-align: left;
  font-family: var(--display); font-size: 1.0625rem; font-weight: 600; letter-spacing: -0.014em; color: var(--ink);
  transition: color 0.2s;
}
.faq-q:hover { color: var(--teal); }
.faq-q .ic { flex: none; width: 20px; height: 20px; margin-top: 2px; position: relative; }
.faq-q .ic::before, .faq-q .ic::after {
  content: ''; position: absolute; top: 50%; left: 50%; translate: -50% -50%;
  background: var(--ink-3); border-radius: 1px; transition: transform 0.32s var(--ease), background 0.2s;
}
.faq-q .ic::before { width: 13px; height: 1.6px; }
.faq-q .ic::after { width: 1.6px; height: 13px; }
.faq-item[data-open] .faq-q { color: var(--teal); }
.faq-item[data-open] .ic::after { transform: scaleY(0); }
.faq-item[data-open] .ic::before { background: var(--teal); }
.faq-a { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.4s var(--ease); }
.faq-item[data-open] .faq-a { grid-template-rows: 1fr; }
.faq-a > div { overflow: hidden; }
.faq-a p { color: var(--ink-2); padding-bottom: 1.35rem; max-width: 68ch; }
.faq-a p + p { padding-top: 0.75rem; }

/* ── Table ────────────────────────────────────────────────────────────── */

.table-scroll { overflow-x: auto; overscroll-behavior-x: contain; border: 1px solid var(--border); border-radius: var(--r); background: var(--surface); }
table { width: 100%; border-collapse: collapse; min-width: 560px; }
th, td { padding: 0.95rem 1.15rem; text-align: left; font-size: 0.9375rem; border-bottom: 1px solid var(--border-soft); }
th { font-family: var(--display); font-weight: 600; font-size: 0.8125rem; letter-spacing: 0.04em; text-transform: uppercase; color: var(--ink-3); background: var(--surface-alt); }
td { color: var(--ink-2); }
td:first-child { color: var(--ink); font-weight: 500; }
tr:last-child td { border-bottom: none; }
td .yes { color: var(--green); font-weight: 600; }
td .no { color: var(--ink-4); }

/* ── Prose (guides) ───────────────────────────────────────────────────── */

.prose { max-width: 68ch; }
.prose > * + * { margin-top: 1.15rem; }
.prose h2 { font-size: clamp(1.5rem, 2.6vw, 1.95rem); margin-top: 3rem; }
.prose h3 { font-size: 1.25rem; margin-top: 2rem; }
.prose p { color: var(--ink-2); }
.prose ul, .prose ol { padding-left: 1.35rem; color: var(--ink-2); }
.prose li + li { margin-top: 0.45rem; }
.prose strong { color: var(--ink); font-weight: 600; }
/* Scoped to real prose links. Badges and buttons inside a callout keep their
   own styling instead of being repainted teal and underlined. */
.prose a:not(.store-badge):not(.btn) {
  color: var(--teal); font-weight: 500;
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-thickness: 1px; text-decoration-color: rgba(0, 132, 108, 0.3);
}
.prose a:not(.store-badge):not(.btn):hover { text-decoration-color: var(--teal); }
.prose blockquote {
  border-left: 3px solid var(--teal-graphic);
  padding: 0.25rem 0 0.25rem 1.35rem;
  color: var(--ink);
  font-size: 1.0625rem;
}
.prose .callout {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r);
  padding: 1.35rem 1.5rem; box-shadow: var(--sh-1);
}
.prose .callout p { margin: 0; }
.prose .callout .eyebrow { display: block; margin-bottom: 0.6rem; }

/* Prose on the dark band.
   `.prose p` and `.band-deep p` have equal specificity, so the later .prose
   rule was winning and painting body copy in dark ink on navy. These are
   scoped one level deeper so the dark band always wins on its own ground. */
.band-deep .prose p,
.band-deep .prose li,
.band-deep .prose ul,
.band-deep .prose ol { color: #B6C4D6; }
.band-deep .prose h2,
.band-deep .prose h3,
.band-deep .prose h4,
.band-deep .prose strong { color: #FFFFFF; }
.band-deep .prose blockquote {
  color: #FFFFFF;
  border-left-color: var(--teal-bright);
}
.band-deep .prose a:not(.store-badge):not(.btn) {
  color: var(--teal-bright);
  text-decoration-color: rgba(0, 212, 170, 0.45);
}
.band-deep .prose a:not(.store-badge):not(.btn):hover { text-decoration-color: var(--teal-bright); }
.band-deep .prose .callout {
  background: var(--deep-2);
  border-color: var(--deep-border);
  box-shadow: none;
}
.band-deep .prose .callout p { color: #B6C4D6; }

/* ── TOC ──────────────────────────────────────────────────────────────── */

.guide-layout { display: grid; grid-template-columns: 220px minmax(0, 720px); gap: clamp(2rem, 5vw, 4.5rem); align-items: start; justify-content: center; }
@media (max-width: 900px) { .guide-layout { grid-template-columns: 1fr; } .toc { display: none; } }
.toc { position: sticky; top: 108px; }
.toc h4 { font-family: var(--mono); font-size: 0.6875rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-4); margin-bottom: 0.75rem; }
.toc a { display: block; padding: 0.35rem 0 0.35rem 0.85rem; font-size: 0.875rem; color: var(--ink-3); border-left: 2px solid var(--border); transition: color 0.2s, border-color 0.2s; }
.toc a:hover, .toc a.active { color: var(--teal); border-left-color: var(--teal); }

/* ── First light ──────────────────────────────────────────────────────────
   A sunrise driven by scroll position: pre-dawn violet through red and gold
   into daylight, with the disc climbing and cooling from ember to white gold.

   Driven by a single custom property, `--dawn` (0 to 1), which app.js updates
   from the band's position. Each layer runs a *paused* one-second animation
   pulled to the right frame with a negative delay, so the browser does the
   interpolation and JS only writes one number per frame.

   This replaced `animation-timeline: view()`. That is the nicer technique on
   paper, but it silently does nothing on engines that lack it and it is also
   killed outright by `prefers-reduced-motion`, which left some people looking
   at a static blob. Correctness on every browser beat elegance on some.

   Reduced motion still gets a still frame, but the *finished* one (daylight,
   sun up) rather than the unstarted one.

   Everything fades out above the copy so text never sits on colour. */

.dawn-band {
  position: absolute; top: clamp(-260px, -20vw, -140px); left: 0; right: 0;
  height: clamp(640px, 68vw, 940px);
  pointer-events: none; z-index: 0;
  --dawn: 1;               /* JS overwrites; 1 = risen, so no-JS looks finished */
  /* Where the water meets the sky. Deliberately lands on the top of the copy
     block, so the sun rises from behind the headline rather than floating in
     empty space. Roughly 43-46% across breakpoints. */
  --horizon: 62%;
}
.section.has-dawn { padding-top: clamp(9rem, 16vw, 15rem); }
.section.has-dawn > .wrap { position: relative; z-index: 1; }

.dawn {
  position: absolute; inset: 0;
  overflow: hidden;
  /* Soft at BOTH ends. Opaque at 0% put a hard seam across the page where the
     band began; it now fades in from nothing and back out below the copy. */
  -webkit-mask-image: linear-gradient(180deg,
    transparent 0%, rgba(0,0,0,0.18) 10%, rgba(0,0,0,0.68) 24%, #000 42%,
    rgba(0,0,0,0.72) 62%, rgba(0,0,0,0.24) 80%, transparent 95%);
  mask-image: linear-gradient(180deg,
    transparent 0%, rgba(0,0,0,0.18) 10%, rgba(0,0,0,0.68) 24%, #000 42%,
    rgba(0,0,0,0.72) 62%, rgba(0,0,0,0.24) 80%, transparent 95%);
}

/* Every animated layer is scrubbed by --dawn. */
.dawn-stage, .disc, .bloom, .rays, .sky-night, .sky-dawn, .sky-day {
  animation-duration: 1s;
  animation-timing-function: linear;
  animation-fill-mode: both;
  animation-play-state: paused;
  animation-delay: calc(var(--dawn) * -1s);
}

.sky { position: absolute; inset: 0; }
.sky-night {
  animation-name: nightFade;
  background:
    radial-gradient(66% 48% at 50% 40%, rgba(128, 96, 205, 0.34) 0%, rgba(128, 96, 205, 0) 66%),
    linear-gradient(180deg, rgba(58, 56, 132, 0.30) 0%, rgba(104, 88, 168, 0.15) 44%, rgba(234, 240, 246, 0) 78%);
}
.sky-dawn {
  animation-name: dawnSweep;
  background:
    radial-gradient(54% 42% at 50% 44%, rgba(255, 138, 118, 0.60) 0%, rgba(255, 138, 118, 0) 62%),
    radial-gradient(84% 56% at 50% 48%, rgba(226, 78, 128, 0.36) 0%, rgba(226, 78, 128, 0) 68%),
    linear-gradient(180deg, rgba(178, 92, 178, 0.24) 0%, rgba(255, 158, 118, 0.16) 48%, rgba(234, 240, 246, 0) 80%);
}
.sky-day {
  animation-name: dayRise;
  background:
    radial-gradient(58% 44% at 50% 42%, rgba(255, 222, 168, 0.44) 0%, rgba(255, 222, 168, 0) 64%),
    linear-gradient(180deg, rgba(178, 205, 228, 0.26) 0%, rgba(214, 231, 241, 0.10) 42%, rgba(234, 240, 246, 0) 76%);
}

.dawn-stage {
  position: absolute; inset: 0;
  /* Was clip-path, which cuts on a hard straight edge. A mask falls off
     gradually, so the disc dissolves toward the waterline with no seam. */
  -webkit-mask-image: linear-gradient(180deg,
    #000 0%, #000 calc(var(--horizon) - 20%),
    rgba(0,0,0,0.55) calc(var(--horizon) - 8%),
    transparent calc(var(--horizon) + 4%));
  mask-image: linear-gradient(180deg,
    #000 0%, #000 calc(var(--horizon) - 20%),
    rgba(0,0,0,0.55) calc(var(--horizon) - 8%),
    transparent calc(var(--horizon) + 4%));
  animation-name: sunClimb;
}
.dawn-sun {
  position: absolute; left: 50%;
  bottom: calc(100% - var(--horizon));   /* resting on the waterline */
  translate: -50% 0;
  width: clamp(132px, 14vw, 190px); aspect-ratio: 1;
}

/* A hard edge is what makes it read as a sun rather than a glow. */
.disc {
  position: absolute; inset: 0; border-radius: 50%;
  animation-name: discWarm;
}
.bloom {
  position: absolute; inset: -145%; border-radius: 50%;
  animation-name: bloomGrow;
  background: radial-gradient(circle,
    rgba(255, 224, 168, 0.50) 0%, rgba(255, 206, 134, 0.24) 28%,
    rgba(255, 186, 120, 0.10) 48%, rgba(255, 186, 120, 0) 68%);
}

/* Discrete irregular rays, not a conic gradient. A gradient looks uniform and
   mushy; rays of differing length and width look like light. */
.rays { position: absolute; inset: 0; animation-name: rayBloom; }
.rays i {
  position: absolute;
  left: 50%; bottom: 50%;
  width: calc(var(--w) * 46px);
  height: calc(var(--len) * 320px);
  margin-left: calc(var(--w) * -23px);
  transform-origin: 50% 100%;
  transform: rotate(var(--a));
  border-radius: 70% 70% 0 0;
  background: linear-gradient(to top,
    rgba(255, 216, 150, 0) 0%,
    rgba(255, 216, 150, 0.55) 38%,
    rgba(255, 216, 150, 0) 100%);
  filter: blur(6px);
  opacity: 0.55;
}
/* The slow turn is real time, not scroll, so it keeps its own timeline. */
.rays-spin { position: absolute; inset: 0; animation: rayTurn 190s linear infinite; }
@keyframes rayTurn { to { transform: rotate(360deg); } }

/* Light on the water. No rule of any kind: it fades in below the waterline
   and out toward the edges, so nothing in this band has a hard boundary. */
.dawn-water {
  position: absolute; left: 0; right: 0; top: var(--horizon); bottom: 0;
  background:
    repeating-linear-gradient(180deg,
      rgba(255, 232, 198, 0.14) 0 1px, rgba(255, 232, 198, 0) 1px 9px),
    linear-gradient(180deg, rgba(255, 214, 160, 0.18) 0%, rgba(158, 190, 216, 0.06) 40%, rgba(234, 240, 246, 0) 100%);
  /* fades in from the waterline as well as out at the edges, so there is no
     line where the water begins either */
  -webkit-mask-image:
    linear-gradient(180deg, transparent 0%, #000 22%),
    radial-gradient(42% 100% at 50% 0%, #000 0%, rgba(0,0,0,0.35) 55%, transparent 88%);
  -webkit-mask-composite: source-in;
  mask-image:
    linear-gradient(180deg, transparent 0%, #000 22%),
    radial-gradient(42% 100% at 50% 0%, #000 0%, rgba(0,0,0,0.35) 55%, transparent 88%);
  mask-composite: intersect;
}

@keyframes sunClimb {
  from { transform: translateY(82%) scale(0.86); }   /* barely breaking the water */
  55%  { transform: translateY(26%) scale(0.95); }
  to   { transform: translateY(-14%) scale(1); }     /* fully clear */
}
@keyframes discWarm {
  from { background: radial-gradient(circle at 50% 42%, #FFD9A8 0%, #FFA871 46%, #F0705F 78%, #D9535F 100%);
         box-shadow: 0 0 22px 6px rgba(232, 110, 96, 0.45); }
  to   { background: radial-gradient(circle at 50% 42%, #FFFCF4 0%, #FFF3D8 46%, #FFE0A8 78%, #FFCE86 100%);
         box-shadow: 0 0 34px 10px rgba(255, 208, 140, 0.55); }
}
@keyframes bloomGrow { from { opacity: 0.5; transform: scale(0.82); } to { opacity: 1; transform: scale(1); } }
@keyframes rayBloom  { from { opacity: 0; } 45% { opacity: 0.2; } to { opacity: 1; } }
@keyframes nightFade { from { opacity: 1; } 30% { opacity: 0.55; } 58% { opacity: 0; } to { opacity: 0; } }
@keyframes dawnSweep { from { opacity: 0.35; } 30% { opacity: 0.9; } 52% { opacity: 1; } 82% { opacity: 0.18; } to { opacity: 0; } }
@keyframes dayRise   { from { opacity: 0; } 55% { opacity: 0.28; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .rays-spin { animation: none; }
}

/* ── Fishdex / species ────────────────────────────────────────────────── */

.rarity {
  display: inline-flex; align-items: center;
  padding: 0.25rem 0.6rem; border-radius: 999px;
  font-family: var(--mono); font-size: 0.6563rem; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase;
}
.r-common    { background: rgba(94, 107, 130, 0.12); color: #4C5768; }
.r-uncommon  { background: rgba(13, 127, 77, 0.12);  color: var(--green); }
.r-rare      { background: rgba(37, 107, 157, 0.12); color: var(--blue); }
.r-legendary { background: rgba(150, 105, 10, 0.14); color: var(--gold-strong); }
.r-mythic    { background: rgba(116, 52, 214, 0.11); color: var(--purple); }

.sp-controls { display: flex; flex-direction: column; gap: 0.75rem; margin-bottom: 2rem; }
.sp-search {
  display: flex; align-items: center; gap: 0.6rem;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 999px; padding: 0 1.1rem; max-width: 380px;
  box-shadow: var(--sh-1);
}
.sp-search svg { width: 16px; height: 16px; flex: none; stroke: var(--ink-3); fill: none; stroke-width: 2; stroke-linecap: round; }
/* 16px is a hard floor, not a taste call. iOS Safari zooms the whole page in
   when a text field smaller than that takes focus, and once it has zoomed the
   canvas pans in both directions until the reader zooms back out by hand. The
   Fishdex and tackle search boxes were at 15px, which is the one tap on the
   site that unlocked the view. */
.sp-search input { flex: 1; border: 0; background: none; padding: 0.7rem 0; font: inherit; font-size: 16px; color: var(--ink); outline: none; }
.sp-search input::placeholder { color: var(--ink-3); }

.sp-filters { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.chip {
  padding: 0.4rem 0.85rem; border-radius: 999px;
  border: 1px solid var(--border); background: var(--surface);
  font-size: 0.8125rem; font-weight: 500; color: var(--ink-2);
  transition: background 0.18s, color 0.18s, border-color 0.18s;
}
.chip:hover { border-color: #CBD7E4; color: var(--ink); }
.chip.active { background: var(--ink); border-color: var(--ink); color: #fff; }
.sp-count { margin-top: 0.25rem; }

.sp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: clamp(0.75rem, 1.6vw, 1.25rem); }
/* auto-FIT, not auto-fill: with only a handful of cards the empty tracks
   collapse so the row spans the full width instead of huddling left. */
.sp-grid-sm { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }

.sp-card {
  /* 601 cards in one grid, so let the browser skip layout and paint for the
     ones off screen. The intrinsic size keeps the scrollbar honest. */
  content-visibility: auto;
  contain-intrinsic-size: auto 253px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r); overflow: hidden;
  box-shadow: var(--sh-1);
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease), border-color 0.3s var(--ease);
  display: flex; flex-direction: column;
}
.sp-card:hover { transform: translateY(-4px); border-color: #D3DFEC; box-shadow: var(--sh-3); }
.sp-card[hidden] { display: none; }
.sp-art {
  aspect-ratio: 4 / 3; display: grid; place-items: center;
  background: linear-gradient(160deg, #F4F8FC, #E6EEF6);
  padding: 0.6rem;
}
.sp-art img { width: 100%; height: 100%; object-fit: contain; transition: transform 0.45s var(--ease); }
.sp-card:hover .sp-art img { transform: scale(1.06); }
/* Fills the remaining card height so the rarity chip can pin to the bottom.
   Without this a two-line scientific name (Hippoglossus hippoglossus) pushed
   its chip down while single-line neighbours left a gap, and the row of cards
   read as ragged. */
.sp-meta { padding: 0.85rem 0.9rem 1rem; display: flex; flex-direction: column; gap: 0.45rem; flex: 1; }
.sp-meta strong { font-family: var(--display); font-size: 0.9375rem; font-weight: 600; color: var(--ink); letter-spacing: -0.012em; line-height: 1.25; }
.sp-meta em { font-family: var(--mono); font-style: normal; font-size: 0.6875rem; color: var(--ink-3); line-height: 1.3; }
/* margin-top:auto pins the chip to the card bottom so every chip in a row
   shares a baseline whatever the name wraps to. The flex gap guarantees
   breathing room when the text is tall enough to meet it. */
.sp-meta .rarity { align-self: flex-start; margin-top: auto; }
.sp-empty { text-align: center; padding: 3rem 0; }

/* Species detail hero */
.sp-hero { display: grid; grid-template-columns: 0.85fr 1.15fr; gap: clamp(1.5rem, 4vw, 3.5rem); align-items: center; }
@media (max-width: 820px) { .sp-hero { grid-template-columns: 1fr; } }
.sp-hero-art {
  background: linear-gradient(160deg, #F4F8FC, #E2ECF6);
  border: 1px solid var(--border); border-radius: var(--r-lg);
  padding: clamp(1.25rem, 3vw, 2.25rem);
  display: grid; place-items: center;
  box-shadow: var(--sh-2);
  aspect-ratio: 4 / 3;
}
.sp-hero-art img { width: 100%; height: 100%; object-fit: contain; }
.sp-sci { font-size: 1rem; color: var(--ink-3); font-style: italic; }

.fact-list { display: grid; gap: 0; border: 1px solid var(--border); border-radius: var(--r); overflow: hidden; background: var(--surface); }
.fact-list > div { display: flex; justify-content: space-between; gap: 1.25rem; padding: 0.85rem 1.1rem; border-bottom: 1px solid var(--border-soft); }
.fact-list > div:last-child { border-bottom: 0; }
.fact-list dt { font-size: 0.875rem; color: var(--ink-3); }
.fact-list dd { font-size: 0.9375rem; color: var(--ink); font-weight: 500; text-align: right; }

/* ── How it works, alternating story steps ────────────────────────────── */

.hiw { display: flex; flex-direction: column; gap: clamp(3.5rem, 7vw, 6rem); }
.hiw-step { display: grid; grid-template-columns: 1fr 0.78fr; gap: clamp(2rem, 5vw, 4.5rem); align-items: center; }
.hiw-step:nth-child(even) .hiw-copy { order: 2; }
@media (max-width: 900px) { .hiw-step { grid-template-columns: 1fr; } .hiw-step:nth-child(even) .hiw-copy { order: 0; } }
.hiw-media { display: grid; place-items: center; }
.hiw-media .phone { max-width: 260px; }

.hiw-n {
  display: block; font-size: 0.75rem; font-weight: 700;
  color: var(--ink-4); letter-spacing: 0.14em; margin-bottom: 0.5rem;
}
.hiw-detail {
  margin-top: 1.1rem; padding-left: 1rem;
  border-left: 2px solid var(--border);
  color: var(--ink-3); font-size: 0.9375rem;
}
.hiw-links { display: flex; flex-wrap: wrap; gap: 1.25rem; margin-top: 1.5rem; }
.hiw-links a {
  display: inline-flex; align-items: center; gap: 0.35rem;
  font-size: 0.9375rem; font-weight: 600; color: var(--teal-strong);
}
.hiw-links svg { width: 14px; transition: transform 0.24s var(--ease); }
.hiw-links a:hover svg { transform: translateX(3px); }

/* Angler titles */
.title-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 0.75rem; }
.title-card {
  background: var(--deep-2); border: 1px solid var(--deep-border);
  border-radius: var(--r); padding: 1.1rem 1.25rem;
  transition: border-color 0.25s var(--ease), transform 0.25s var(--ease);
}
.title-card:hover { border-color: rgba(0, 212, 170, 0.4); transform: translateY(-3px); }
.title-card strong {
  display: block; font-family: var(--display); font-size: 1.0625rem;
  font-weight: 600; color: #fff; letter-spacing: -0.014em;
}
.title-card span { display: block; font-size: 0.8438rem; color: #8494AD; margin-top: 0.3rem; line-height: 1.45; }

/* ── CTA band ─────────────────────────────────────────────────────────── */

.cta-band { text-align: center; }
.cta-band h2 { max-width: 18ch; margin-inline: auto; }
.cta-band .lede { max-width: 52ch; margin: 1.25rem auto 2rem; }

/* ── Footer ───────────────────────────────────────────────────────────── */

.site-footer { background: var(--deep); color: #8494AD; padding-block: clamp(3.5rem, 7vw, 5.5rem) 2.5rem; }
.footer-grid { display: grid; grid-template-columns: 1.4fr repeat(4, 1fr); gap: 2.5rem 1.5rem; }
@media (max-width: 900px) { .footer-grid { grid-template-columns: repeat(2, 1fr); } .footer-brand { grid-column: 1 / -1; } }
@media (max-width: 520px) { .footer-grid { grid-template-columns: 1fr 1fr; } }
.footer-brand .wordmark { font-size: 1.6rem; color: #fff; }
.footer-brand p { color: #8494AD; font-size: 0.9375rem; margin-top: 0.85rem; max-width: 30ch; }
.site-footer h4 { color: #fff; font-size: 0.6875rem; font-family: var(--mono); letter-spacing: 0.16em; text-transform: uppercase; margin-bottom: 1rem; font-weight: 700; }
.site-footer nav a { display: block; font-size: 0.9063rem; color: #8494AD; padding: 0.28rem 0; transition: color 0.2s; }
.site-footer nav a:hover { color: var(--teal-bright); }
.social-row { display: flex; gap: 0.5rem; margin-top: 1.5rem; }
.social-row a {
  width: 38px; height: 38px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  transition: background 0.2s, border-color 0.2s, transform 0.2s var(--ease);
}
.social-row a:hover { background: rgba(0, 212, 170, 0.14); border-color: rgba(0, 212, 170, 0.4); transform: translateY(-2px); }
.social-row svg {
  width: 17px; height: 17px;
  stroke: #A0B0C4; fill: none;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
  transition: stroke 0.2s;
}
.social-row a:hover svg { stroke: var(--teal-bright); }

/* Founder portrait.
   The image is taller than its frame and pans slowly as the section crosses the
   viewport. This uses native CSS scroll-driven animation (animation-timeline:
   view()), so it runs off the main thread and needs no JavaScript and no
   library. Browsers without support get a still, correctly-cropped photo. */
.portrait {
  position: relative;
  width: 100%; max-width: 480px; margin-inline: auto;
  aspect-ratio: 4 / 5;
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--sh-3);
  isolation: isolate;
}
.portrait::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14);
  pointer-events: none; z-index: 2;
}
.portrait img {
  width: 100%; height: 118%;
  object-fit: cover; object-position: center 38%;
  transform: translateY(-10%) scale(1.02);
  will-change: transform;
}
.portrait figcaption {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 1;
  padding: 2.75rem 1.5rem 1.35rem;
  background: linear-gradient(transparent, rgba(6, 14, 26, 0.78));
  color: #fff;
}
.portrait figcaption strong { display: block; font-family: var(--display); font-size: 1rem; font-weight: 600; letter-spacing: -0.012em; }
.portrait figcaption span { display: block; font-size: 0.8125rem; color: rgba(255, 255, 255, 0.72); margin-top: 1px; }

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .portrait img {
      animation: portraitPan linear both;
      animation-timeline: view();
      animation-range: entry 0% exit 100%;
    }
    @keyframes portraitPan {
      /* the anglers sit low in the source frame, so the window stays on the
         lower two thirds instead of drifting up into empty sky */
      from { transform: translateY(-14%) scale(1.05); }
      to   { transform: translateY(-6%) scale(1); }
    }
    .portrait figcaption {
      animation: captionRise linear both;
      animation-timeline: view();
      animation-range: entry 20% entry 85%;
    }
    @keyframes captionRise {
      from { opacity: 0; transform: translateY(14px); }
      to   { opacity: 1; transform: none; }
    }
  }
}

/* No rule above the sign-off: the signature already separates it from the copy. */
.founder-sign { margin-top: 2rem; }

/* Signature. Real ink is never pure black, so it sits a touch lighter than the
   heading it signs off. The SVG uses currentColor and scales without loss. */
.signature { color: var(--ink); opacity: 0.94; margin-bottom: 0.55rem; }
/* Sized by HEIGHT, not width. The ascender and descender make this mark
   naturally tall, so constraining the width let it tower over the name it
   signs. Height-driven keeps it at roughly 2.5x the name, which reads as
   ink rather than as a logo. */
.signature svg { height: clamp(56px, 7vw, 82px); width: auto; display: block; overflow: visible; }

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .signature svg {
      animation: signWipe linear both;
      animation-timeline: view();
      animation-range: entry 45% entry 92%;
    }
    /* a fill cannot be stroke-drawn, so it is revealed left to right instead */
    @keyframes signWipe {
      from { clip-path: inset(0 100% 0 0); }
      to   { clip-path: inset(0 0 0 0); }
    }
  }
}
.founder-sign strong { display: block; font-family: var(--display); font-size: 1.0625rem; font-weight: 600; color: var(--ink); letter-spacing: -0.012em; }
.founder-sign span { display: block; font-size: 0.875rem; color: var(--ink-3); margin-top: 2px; }

.footer-bottom { display: flex; flex-wrap: wrap; gap: 1rem; justify-content: space-between; align-items: center; margin-top: 3.5rem; padding-top: 1.75rem; border-top: 1px solid var(--deep-border); font-size: 0.8438rem; }
.footer-bottom a:hover { color: var(--teal-bright); }
.footer-legal { display: flex; flex-wrap: wrap; gap: 1.25rem; }

/* ── Breadcrumb ───────────────────────────────────────────────────────── */

.crumb { display: flex; flex-wrap: wrap; align-items: center; gap: 0.45rem; font-size: 0.8438rem; color: var(--ink-3); margin-bottom: 1.5rem; }
.crumb a:hover { color: var(--teal); }
.crumb svg { width: 12px; opacity: 0.5; stroke: currentColor; fill: none; stroke-width: 2.2; }

/* ── Page hero (interior) ─────────────────────────────────────────────── */

.page-hero { padding-block: clamp(1.75rem, 3vw, 2.75rem) clamp(2rem, 3.5vw, 3rem); position: relative; overflow: hidden; }
.page-hero::before {
  content: ''; position: absolute; top: -40%; left: 50%; translate: -50% 0;
  width: 900px; height: 700px; border-radius: 50%;
  background: radial-gradient(circle, rgba(0, 212, 170, 0.13), transparent 66%);
  filter: blur(70px); pointer-events: none;
}
.page-hero .wrap { position: relative; z-index: 1; }
.page-hero h1 { margin-block: 0.9rem; }
.page-hero .lede { max-width: 62ch; }

/* ── Misc ─────────────────────────────────────────────────────────────── */

.hr { height: 1px; background: var(--border); border: 0; }
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--teal); color: #fff; padding: 0.75rem 1.25rem; border-radius: 0 0 12px 0;
}
.skip:focus { left: 0; }

:focus-visible { outline: 2px solid var(--teal); outline-offset: 3px; border-radius: 6px; }

.quote-mark { font-family: var(--display); font-size: 3rem; line-height: 0.6; color: rgba(0, 132, 108, 0.28); }

.note {
  font-size: 0.875rem; color: var(--ink-3);
  border-left: 2px solid var(--border); padding-left: 1rem;
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .js [data-r], .js [data-r-stagger] > * { opacity: 1 !important; transform: none !important; }
  .js .reveal-words .w > .ww { transform: none !important; }
  .js .showcase-step { opacity: 1 !important; }
  .js .showcase-stage .phone { opacity: 1 !important; }
  .js .showcase-stage .phone:not(:first-child) { display: none; }
  .hero-bg { display: none; }
}

/* ── Tackle library ───────────────────────────────────────────────────────
   Lure art is photographed on white by the retailers it came from, so the
   card wells stay near-white. A blue-grey well like the species cards use
   would make every product look like it had been cut out badly.          */

.tk-controls { display: flex; flex-direction: column; gap: 0.75rem; margin-bottom: 2rem; }
.tk-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: clamp(0.75rem, 1.6vw, 1.25rem); }
.tk-grid-sm { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }

.tk-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r); overflow: hidden; box-shadow: var(--sh-1);
  display: flex; flex-direction: column;
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease), border-color 0.3s var(--ease);
}
.tk-card:hover { transform: translateY(-4px); border-color: #D3DFEC; box-shadow: var(--sh-3); }
.tk-card[hidden] { display: none; }
/* place-items:stretch plus min-height:0, not place-items:center. A centred grid
   item is content-sized, so a tall image overrides the aspect-ratio and stretches
   the card. Stretching the item and zeroing its min size keeps the box honest
   whatever the source dimensions turn out to be. */
/* Plain white, not a gradient. The catalogue art is retailer product
   photography shot on white and the CDN pads it to a square on white, so any
   tinted well shows a hard seam where the padding ends. */
.tk-card-art {
  aspect-ratio: 4 / 3; display: grid;
  background: #fff; border-bottom: 1px solid var(--border-soft);
  padding: 0.9rem;
}
.tk-card-art img { width: 100%; height: 100%; min-width: 0; min-height: 0; object-fit: contain; transition: transform 0.45s var(--ease); }
.tk-card:hover .tk-card-art img { transform: scale(1.06); }
.tk-card-meta { padding: 0.85rem 0.95rem 1rem; display: flex; flex-direction: column; gap: 0.3rem; flex: 1; }
.tk-card-meta strong { font-family: var(--display); font-size: 0.9688rem; font-weight: 600; color: var(--ink); letter-spacing: -0.012em; line-height: 1.25; }
.tk-card-meta .tiny { margin-top: auto; }

/* Type page hero */
.tk-hero { display: grid; grid-template-columns: 1.05fr 0.95fr; gap: clamp(1.5rem, 4vw, 3.5rem); align-items: center; }
@media (max-width: 880px) { .tk-hero { grid-template-columns: 1fr; } }
.tk-hero-stats { display: flex; gap: clamp(1.5rem, 4vw, 2.75rem); margin-top: 1.75rem; }
.tk-hero-stats div { display: flex; flex-direction: column; gap: 0.15rem; }
.tk-hero-stats b { font-family: var(--display); font-size: clamp(1.35rem, 2.6vw, 1.75rem); font-weight: 700; color: var(--ink); letter-spacing: -0.02em; }
.tk-hero-stats span { font-size: 0.8125rem; color: var(--ink-3); }
.tk-hero-art { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; }
.tk-hero-art figure {
  background: #fff;
  border: 1px solid var(--border); border-radius: var(--r);
  aspect-ratio: 1; display: grid; padding: 0.9rem;
  box-shadow: var(--sh-1);
}
.tk-hero-art img { width: 100%; height: 100%; min-width: 0; min-height: 0; object-fit: contain; }

.tk-callout {
  margin-top: 2.5rem; background: var(--surface);
  border: 1px solid var(--border); border-left: 3px solid var(--copper);
  border-radius: var(--r); padding: 1.25rem 1.4rem;
}
.tk-callout .eyebrow { display: block; margin-bottom: 0.55rem; }
.tk-callout p { margin: 0; color: var(--ink-2); }

/* Species fit chips */
.tk-sp-h { margin: 2rem 0 0.9rem; font-size: 1.0625rem; color: var(--ink-2); }
.tk-sp-row { display: flex; flex-wrap: wrap; gap: 0.45rem; }
.tk-sp {
  display: inline-flex; align-items: center;
  padding: 0.45rem 0.9rem; border-radius: 999px;
  border: 1px solid var(--border); background: var(--surface);
  font-size: 0.875rem; font-weight: 500; color: var(--ink-2);
  box-shadow: var(--sh-1);
  transition: border-color 0.2s, color 0.2s, transform 0.2s var(--ease);
}
a.tk-sp:hover { border-color: var(--teal); color: var(--teal-strong); transform: translateY(-2px); }
.tk-sp-flat { box-shadow: none; color: var(--ink-3); }
.tk-sp-row-dim .tk-sp { background: transparent; }

/* Colour availability bars */
.tk-bars { list-style: none; display: grid; gap: 0.7rem; }
.tk-bars li { display: grid; grid-template-columns: 1fr; gap: 0.35rem; }
.tk-bars span { font-size: 0.875rem; color: var(--ink-2); }
.tk-bars i { display: block; height: 8px; border-radius: 999px; background: var(--border); position: relative; overflow: hidden; }
.tk-bars i::after {
  content: ''; position: absolute; inset: 0 auto 0 0; width: var(--w);
  border-radius: 999px; background: linear-gradient(90deg, var(--blue-graphic), var(--teal-graphic));
}

/* Widely stocked picks */
.tk-picks { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: clamp(0.75rem, 1.6vw, 1.25rem); }
.tk-pick {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r); overflow: hidden; box-shadow: var(--sh-1);
}
.tk-pick-art {
  aspect-ratio: 1; display: grid; padding: 1rem;
  background: #fff; border-bottom: 1px solid var(--border-soft);
}
.tk-pick-art img { width: 100%; height: 100%; min-width: 0; min-height: 0; object-fit: contain; }
.tk-pick figcaption { padding: 0.85rem 0.95rem 1rem; display: flex; flex-direction: column; gap: 0.2rem; }
.tk-pick figcaption strong { font-family: var(--display); font-size: 0.9375rem; font-weight: 600; color: var(--ink); line-height: 1.25; }
.tk-pick figcaption span { font-size: 0.8125rem; color: var(--ink-2); }
.tk-pick figcaption em { font-style: normal; color: var(--ink-3); }

/* The tease. Nothing here is hidden text — the bars are decorative elements
   with no content, so a crawler and a reader see exactly the same page. */
.tk-tease {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-lg); padding: clamp(1.5rem, 4vw, 2.75rem);
  box-shadow: var(--sh-2);
  display: grid; gap: 1.75rem;
}
.tk-tease-head .lede { margin-top: 0.9rem; }
.tk-tease-head .h2 { margin-top: 0.7rem; }
.tk-tease-panel {
  background: linear-gradient(165deg, var(--deep), var(--deep-2));
  border: 1px solid var(--deep-border); border-radius: var(--r);
  padding: clamp(1.1rem, 2.5vw, 1.6rem);
  display: grid; gap: 0.85rem;
}
.tk-tease-panel-solo { width: 100%; }
.tk-tease-row { display: flex; align-items: center; justify-content: space-between; gap: 1.25rem; }
.tk-tease-k { font-size: 0.9375rem; color: #C2D2E6; }
.tk-tease-v { display: inline-flex; align-items: center; gap: 0.55rem; flex: none; width: clamp(90px, 26%, 170px); color: var(--gold-graphic); }
.tk-lock-ic { width: 14px; height: 14px; flex: none; }
.tk-tease-v i {
  display: block; height: 9px; width: var(--w); border-radius: 999px;
  background: repeating-linear-gradient(115deg, rgba(217,154,16,0.42) 0 6px, rgba(217,154,16,0.16) 6px 12px);
}
.tk-tease-note { color: #8FA5C0; margin-top: 0.4rem; }
.tk-tease .btn-row { margin: 0; }

/* Brand index */
.tk-brands { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: var(--r); overflow: hidden; }
.tk-brand { background: var(--surface); padding: 0.85rem 1.05rem; display: flex; flex-direction: column; gap: 0.15rem; }
.tk-brand strong { font-family: var(--display); font-size: 0.9375rem; font-weight: 600; color: var(--ink); }

@media (max-width: 620px) {
  .tk-hero-art { grid-template-columns: 1fr 1fr; }
  .tk-tease-row { flex-direction: column; align-items: flex-start; gap: 0.4rem; }
  .tk-tease-v { width: 100%; }
}

/* Inline links inside checklist copy. The global reset makes anchors inherit,
   which is right for cards and nav and wrong for a link inside a sentence. */
.checklist a {
  color: var(--teal-strong);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  text-decoration-color: rgba(0, 115, 94, 0.4);
  transition: text-decoration-color 0.2s;
}
.checklist a:hover { text-decoration-color: currentColor; }
.band-deep .checklist a { color: var(--teal-bright); text-decoration-color: rgba(0, 212, 170, 0.45); }

/* Species fit on a tackle type page. Reuses the Fishdex card so a species looks
   the same everywhere on the site; only the extras are new. */
.tk-sp-grid { margin-top: 0.25rem; }
.tk-sp-grid-dim .sp-card { box-shadow: none; }
.tk-sp-grid-dim .sp-art { opacity: 0.9; }
/* The affinity table keys off broad groups, so show the group name under the
   species when they differ ("Redfish and Red Drum" over Red Drum). */
.tk-sp-group { font-family: var(--body) !important; font-size: 0.75rem !important; color: var(--ink-3); font-style: normal; }
.tk-sp-card .sp-meta { gap: 0.35rem; }

/* Row of unresolved group names sits below the card grid, so a pill is never
   stretched to fill a card-sized grid cell. */
.tk-sp-row { margin-top: 1rem; }

/* Orphan-free card grid. Column counts come from the item count via fitGrid()
   in kit.mjs; the breakpoints stay here. */
.tk-fit {
  display: grid;
  gap: clamp(0.75rem, 1.6vw, 1.25rem);
  grid-template-columns: repeat(var(--cw, 4), minmax(0, 1fr));
}
@media (max-width: 1000px) { .tk-fit { grid-template-columns: repeat(var(--cm, 3), minmax(0, 1fr)); } }
@media (max-width: 620px)  { .tk-fit { grid-template-columns: repeat(var(--cn, 2), minmax(0, 1fr)); } }

/* Wind flow field behind the weather hero. Sits under .wrap (z-index 1) and is
   clipped by .page-hero's overflow:hidden. Never intercepts a pointer event. */
.wind-bg { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
.wind-bg canvas { width: 100%; height: 100%; display: block; }
@media (prefers-reduced-motion: reduce) { .wind-bg { display: none; } }
