/* marketing.css — standalone landing page (index.html) for 99northmedia.com.
 *
 * Self-contained component system (mkt- prefix) so it never collides with the
 * app's styles.css. Dark-brand only (the landing page is locked to dark in the
 * <head>). All colors come from tokens.css — no hardcoded palette. Responsive
 * via clamp()/grid; the page body never scrolls horizontally. */

/* ---- the page shape ------------------------------------------------------- */
/* One frame for every public page. tokens.css defaults these to the full-width
   case for the app; here they take the marketing value, and the top bar and each
   page's <main> both read them, so a page and the bar above it are the same
   shape by construction rather than by two files agreeing. */
:root { --page-max: 1400px; --page-gutter: 2rem; }
@media (max-width: 768px) { :root { --page-gutter: 1rem; } }
main {
    max-width: var(--page-max); margin: 0 auto;
    padding: 2rem var(--page-gutter);
}

/* ---- shell ---------------------------------------------------------------- */
body {
    margin: 0;
    background: var(--bg-base);
    color: var(--text-primary);
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    overflow-x: hidden;
}
.mkt-wrap { max-width: 1200px; margin: 0 auto; padding: 0 24px; }
.mkt-eyebrow {
    text-transform: uppercase; letter-spacing: 0.14em; font-size: 0.72rem;
    font-weight: 700; color: var(--brand-secondary); margin: 0 0 14px;
}

/* ---- slim top bar --------------------------------------------------------- */
.mkt-nav {
    position: sticky; top: 0; z-index: 100;
    padding: 12px 0;
    background: color-mix(in srgb, var(--bg-base) 82%, transparent);
    backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--border-soft);
}
/* The bar spans the window so its wash and rule do; the row inside sits on the
   page box, so the mark lands on the left edge of the hero, the stat panel and
   the cards, and the auth group on their right. Row and page box read the same
   two tokens — the frame tokens.css already defines for exactly this — so they
   cannot drift apart, and one page cannot end up a different shape from the
   next. */
.mkt-nav-row {
    max-width: var(--page-max); margin: 0 auto; padding: 0 var(--page-gutter);
    display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.mkt-nav-brand { display: flex; align-items: center; text-decoration: none; }
/* The mark carries the name, so it stands alone — at a size the wordmark inside
   it can actually be read at, which the old 30px beside a text label was not. */
.mkt-nav-brand img { height: 44px; width: auto; display: block; }
/* styles.css caps and centres every <nav> row to --page-max. That is right for
   the app's own header, where the nav IS the row; here the row is .mkt-nav-row
   and the same rule would centre the links inside it. */
.mkt-nav .mkt-nav-links { max-width: none; margin: 0; padding: 0; }
/* The brand mark ships as white ink on transparency — one asset, because the
   shield is a single-colour mark and a second file would be a second thing to
   keep in sync. index.html is locked to dark, but pricing and offlinecut honour
   the signed-in user's stored theme, so on the two light ones the same white
   ink is inverted to black rather than vanishing into the page. */
[data-theme="light"] .mkt-nav-brand img,
[data-theme="sepia"] .mkt-nav-brand img,
[data-theme="light"] .mkt-footer-brand img,
[data-theme="sepia"] .mkt-footer-brand img { filter: invert(1); }
.mkt-nav-links { display: flex; align-items: center; gap: 8px; }
.mkt-nav-links a.mkt-navlink {
    color: var(--text-secondary); text-decoration: none; font-size: 0.9rem; font-weight: 500;
    padding: 8px 12px; border-radius: 8px; transition: color .15s, background .15s;
}
.mkt-nav-links a.mkt-navlink:hover { color: var(--text-primary); background: var(--bg-elevated); }
.mkt-nav-list { display: flex; align-items: center; gap: 4px; list-style: none; margin: 0; padding: 0; }
/* The Download dropdown is shared markup driven by nav-menu.js, and its base
   styles are the old nav's — uppercase, bold, no hit area. Inside this bar it
   has to read as one of the links beside it. */
.mkt-nav .nav-menu-button.mkt-navlink {
    text-transform: none; letter-spacing: normal; font-weight: 500;
    color: var(--text-secondary); padding: 8px 12px; border-radius: 8px;
    transition: color .15s, background .15s;
}
.mkt-nav .nav-menu-button.mkt-navlink:hover { color: var(--text-primary); background: var(--bg-elevated); }

/* InlineAuth (in <head>) forces the auth containers to display:block!important;
   this inner group does the row layout so the block toggle keeps working. */
.mkt-authgroup { display: inline-flex; align-items: center; gap: 10px; vertical-align: middle; }

/* buttons (shared) */
.mkt-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    font-weight: 600; font-size: 0.9rem; line-height: 1; cursor: pointer;
    padding: 11px 18px; border-radius: 10px; text-decoration: none;
    border: 1px solid transparent; transition: transform .12s, background .15s, border-color .15s, box-shadow .15s;
    white-space: nowrap;
}
.mkt-btn:active { transform: translateY(1px); }
.mkt-btn-primary {
    background: var(--brand-primary); color: var(--text-inverse);
    box-shadow: 0 6px 20px color-mix(in srgb, var(--brand-primary) 35%, transparent);
}
.mkt-btn-primary:hover { background: color-mix(in srgb, var(--brand-primary) 88%, #fff); }
.mkt-btn-ghost { background: transparent; color: var(--text-primary); border-color: var(--border-default); }
.mkt-btn-ghost:hover { border-color: var(--border-strong); background: var(--bg-elevated); }
.mkt-btn-lg { padding: 15px 26px; font-size: 1rem; border-radius: 12px; }

/* The primary call to action, carrying the beta's remaining seats under it.
   Two lines of different weight: the offer, then the scarcity. The count is
   painted by beta-seats.js, so a button that never receives one simply stays
   the single centred line it was authored as.

   It is also the one place the shared nowrap has to give: this label is a
   phrase rather than a word, and on a narrow screen a phrase that cannot wrap
   is what pushes the whole page into a sideways scroll. The button already
   reads as centred lines, so wrapping costs it nothing. */
.mkt-btn-stack { flex-direction: column; gap: 5px; line-height: 1.25; padding: 16px 34px; max-width: 100%; white-space: normal; text-align: center; }
.mkt-btn-stack .beta-cta-lead { font-size: 1.05rem; font-weight: 700; letter-spacing: -0.01em; }
.mkt-btn-stack .beta-cta-count {
    font-size: 0.78rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase;
    opacity: 0.82;
}

/* ---- hero ----------------------------------------------------------------- */
.mkt-hero { position: relative; overflow: hidden; isolation: isolate; }
.mkt-hero-video {
    position: absolute; inset: 0; width: 100%; height: 100%;
    object-fit: cover; z-index: -2; opacity: 0.55;
}
.mkt-hero::after { /* legibility + brand wash */
    content: ''; position: absolute; inset: 0; z-index: -1;
    background:
        radial-gradient(1000px 500px at 70% -10%, color-mix(in srgb, var(--brand-secondary) 22%, transparent), transparent 70%),
        linear-gradient(180deg, color-mix(in srgb, var(--bg-base) 55%, transparent) 0%, var(--bg-base) 82%);
}
.mkt-hero-inner { padding: clamp(56px, 11vw, 128px) 0 clamp(40px, 7vw, 80px); text-align: center; }
.mkt-hero h1 {
    margin: 0 auto 20px; max-width: 16ch;
    font-size: clamp(2.1rem, 5.4vw, 4rem); line-height: 1.05; letter-spacing: -0.02em;
    font-weight: 800; color: var(--text-inverse);
}
.mkt-hero h1 .mkt-accent { color: var(--brand-primary); }
.mkt-hero p.mkt-sub {
    margin: 0 auto 30px; max-width: 60ch;
    font-size: clamp(1.02rem, 2vw, 1.28rem); line-height: 1.55; color: var(--text-secondary);
}
.mkt-hero-cta { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }
/* An explicit display beats the `hidden` attribute, so hiding these in script
   does nothing without this — the phone would show the buttons AND the signup
   form at once. Same reason the quick-signup forms carry it. */
.mkt-hero-cta[hidden], .mkt-quick[hidden], .mkt-quick-form[hidden] { display: none; }

/* ---- phone quick signup --------------------------------------------------- */
/* Shown instead of the hero buttons at phone widths. Deliberately plain: one
   field, one button, and enough tap target that a thumb hits it first time. */
.mkt-quick { max-width: 420px; margin: 0 auto; text-align: left; }
.mkt-quick-form { margin: 0 0 10px; }
.mkt-quick-label {
    display: block; margin: 0 0 8px; font-size: 0.92rem; font-weight: 600;
    color: var(--text-secondary); text-align: center;
}
.mkt-quick-row { display: flex; gap: 8px; }
.mkt-quick-input {
    flex: 1 1 auto; min-width: 0;
    /* 16px or larger, or iOS Safari zooms the page on focus and the layout
       jumps under the thumb mid-typing. */
    font-size: 1rem; padding: 14px 14px; border-radius: 10px;
    background: var(--bg-elevated); color: var(--text-primary);
    border: 1px solid var(--border-default);
}
.mkt-quick-input:focus { outline: none; border-color: var(--brand-primary); }
.mkt-quick-code { letter-spacing: 0.3em; text-align: center; font-variant-numeric: tabular-nums; }
.mkt-quick-btn { flex: 0 0 auto; padding: 14px 20px; font-size: 1rem; }
.mkt-quick-link {
    display: block; margin: 10px auto 0; padding: 6px;
    background: none; border: none; cursor: pointer; font: inherit;
    font-size: 0.88rem; color: var(--text-muted); text-decoration: underline;
}
/* The password offer's own two lines: the "or skip" half of the label, and the
   policy this environment enforces. Both are asides to a step that is optional
   by design, so neither competes with the field. */
.mkt-quick-optional { font-weight: 500; color: var(--text-muted); }
.mkt-quick-rules {
    margin: 0 0 8px; text-align: center; font-size: 0.8rem; color: var(--text-muted);
}
.mkt-quick-rules:empty { display: none; }
.mkt-quick-status { margin: 10px 0 0; text-align: center; font-size: 0.9rem; min-height: 1.2em; }
.mkt-quick-status.is-error { color: var(--status-error, #ff6b6b); }
.mkt-quick-status.is-ok { color: var(--brand-secondary); }
.mkt-quick-terms { margin: 14px 0 0; text-align: center; font-size: 0.78rem; color: var(--text-muted); }
.mkt-quick-terms a { color: var(--text-secondary); }

/* ---- live stats band ------------------------------------------------------ */
.mkt-stats { border-top: 1px solid var(--border-soft); border-bottom: 1px solid var(--border-soft); background: var(--bg-sunken); }
.mkt-stats.mkt-hidden { display: none; }
.mkt-stats-grid {
    display: grid; grid-template-columns: repeat(4, 1fr);
    gap: 1px; background: var(--border-soft);
}
.mkt-stat { background: var(--bg-sunken); padding: clamp(22px, 4vw, 40px) 16px; text-align: center; }
.mkt-stat-num {
    font-size: clamp(1.7rem, 4.4vw, 3rem); font-weight: 800; letter-spacing: -0.02em;
    color: var(--text-inverse); font-variant-numeric: tabular-nums; line-height: 1;
}
.mkt-stat-num .mkt-unit { font-size: 0.5em; color: var(--brand-secondary); margin-left: 4px; font-weight: 700; }
.mkt-stat-label { margin-top: 10px; font-size: 0.8rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.08em; font-weight: 600; }

/* ---- generic section ------------------------------------------------------ */
.mkt-section { padding: clamp(56px, 9vw, 104px) 0; }
.mkt-section-head { text-align: center; max-width: 62ch; margin: 0 auto clamp(36px, 5vw, 56px); }
.mkt-section-head h2 { margin: 0 0 14px; font-size: clamp(1.7rem, 3.6vw, 2.6rem); line-height: 1.12; letter-spacing: -0.02em; font-weight: 800; color: var(--text-inverse); }
.mkt-section-head p { margin: 0; font-size: clamp(1rem, 1.8vw, 1.15rem); line-height: 1.6; color: var(--text-secondary); }

/* ---- product showcase ----------------------------------------------------- */
.mkt-showcase { display: grid; grid-template-columns: 1fr 1.35fr; gap: clamp(28px, 5vw, 64px); align-items: center; }
.mkt-showcase-copy h3 { margin: 0 0 14px; font-size: clamp(1.4rem, 3vw, 2rem); letter-spacing: -0.01em; font-weight: 800; color: var(--text-inverse); }
.mkt-showcase-copy p { margin: 0 0 20px; font-size: 1.05rem; line-height: 1.6; color: var(--text-secondary); }
.mkt-feat-list { list-style: none; margin: 0 0 26px; padding: 0; display: grid; gap: 12px; }
.mkt-feat-list li { display: flex; gap: 12px; align-items: flex-start; color: var(--text-secondary); font-size: 0.98rem; line-height: 1.45; }
.mkt-feat-list li b { color: var(--text-primary); font-weight: 600; }
.mkt-check {
    flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%; margin-top: 1px;
    background: color-mix(in srgb, var(--brand-secondary) 18%, transparent);
    color: var(--brand-secondary); display: inline-flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 800;
}
.mkt-shot-frame {
    border-radius: 14px; overflow: hidden; border: 1px solid var(--border-default);
    background: var(--bg-elevated); box-shadow: 0 30px 80px rgba(0,0,0,0.55);
}
.mkt-shot-frame img { display: block; width: 100%; height: auto; }

/* ---- platform strip ------------------------------------------------------- */
.mkt-platforms { display: flex; flex-wrap: wrap; gap: 10px 26px; justify-content: center; align-items: center; }
.mkt-platform-chip {
    display: inline-flex; align-items: center; gap: 9px; padding: 10px 18px; border-radius: 999px;
    background: var(--bg-elevated); border: 1px solid var(--border-soft); color: var(--text-secondary);
    font-weight: 600; font-size: 0.92rem;
}
.mkt-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--brand-primary); }
/* The why-section reuses the platform strip for its no-install claims: same
   chip, so the two rows read as one vocabulary. It only needs the gap the
   section head does not provide. */
.mkt-why-chips { margin: 0 0 clamp(30px, 4vw, 42px); }

/* ---- three feature cards -------------------------------------------------- */
.mkt-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.mkt-card {
    background: var(--bg-elevated); border: 1px solid var(--border-soft); border-radius: 14px;
    padding: 28px 24px; transition: transform .15s, border-color .15s;
}
.mkt-card:hover { transform: translateY(-3px); border-color: var(--border-strong); }
/* Mark then label, on one line. Reading it as a single row — icon, name —
   is quieter than a badge floated to the far edge, and it keeps the two
   tied together as the columns narrow. Centred rather than top-aligned
   because both sit on one text line. */
.mkt-card-head { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.mkt-card-head h3 { margin: 0; }
/* Brand primary, not secondary — the blue read as a stray system accent
   against an otherwise orange page. */
.mkt-card-icon { width: 40px; height: 40px; flex: 0 0 40px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 20px; background: color-mix(in srgb, var(--brand-primary) 14%, transparent); color: var(--brand-primary); }
/* The mark is the same Font Awesome solid glyph the app shows for that concept
   (see js/nav-icons.js) — sized by the box, not by an em, so glyphs whose
   viewBox is wider than tall (photo-film, cloud-arrow-up) do not outgrow the
   tile. fill=currentColor on the svg picks up the accent above. */
.mkt-card-icon svg { width: 20px; height: 20px; display: block; }
/* No bottom margin: every card label lives inside .mkt-card-head, which owns the
   gap to the paragraph below it. The margin used to live here and, being a later
   rule of equal specificity, quietly beat the head's own reset — so the label's
   box was 8px taller than the label, and centring the row put the mark 4px below
   the word beside it on every card on the page. */
.mkt-card h3 { margin: 0; font-size: 1.15rem; color: var(--text-inverse); font-weight: 700; }
.mkt-card p { margin: 0; font-size: 0.95rem; line-height: 1.55; color: var(--text-secondary); }
/* The why-section runs four stages rather than three; it drops to two across
   before it drops to one, because the stages read as a sequence and a single
   column loses that. */
.mkt-cards-4 { grid-template-columns: repeat(4, 1fr); }
.mkt-why-note {
    margin: 26px auto 0; max-width: 720px; text-align: center;
    font-size: 1.02rem; line-height: 1.6; color: var(--text-secondary);
}

/* ---- adventure gallery ---------------------------------------------------- */
.mkt-gallery { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; }
.mkt-gallery figure { position: relative; margin: 0; border-radius: 12px; overflow: hidden; aspect-ratio: 4 / 5; background: var(--bg-elevated); }
.mkt-gallery img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .4s ease; }
.mkt-gallery figure:hover img { transform: scale(1.05); }

/* ---- closing CTA ---------------------------------------------------------- */
.mkt-cta-band { text-align: center; }
.mkt-cta-card {
    background: linear-gradient(140deg, color-mix(in srgb, var(--brand-secondary) 16%, var(--bg-elevated)), var(--bg-elevated));
    border: 1px solid var(--border-default); border-radius: 20px; padding: clamp(40px, 7vw, 72px) 24px;
}
.mkt-cta-card h2 { margin: 0 0 14px; font-size: clamp(1.6rem, 3.6vw, 2.6rem); font-weight: 800; color: var(--text-inverse); letter-spacing: -0.02em; }
.mkt-cta-card p { margin: 0 0 26px; color: var(--text-secondary); font-size: 1.1rem; }

/* ---- footer --------------------------------------------------------------- */
.mkt-footer { border-top: 1px solid var(--border-soft); background: var(--bg-sunken); padding: 48px 0 32px; margin-top: 8px; }
.mkt-footer-top { display: flex; flex-wrap: wrap; gap: 28px; justify-content: space-between; align-items: flex-start; }
.mkt-footer-brand { display: flex; align-items: center; gap: 10px; text-decoration: none; }
.mkt-footer-brand img { height: 28px; }
.mkt-footer-brand span { font-weight: 800; color: var(--text-primary); }
.mkt-footer-links { display: flex; flex-wrap: wrap; gap: 10px 28px; }
.mkt-footer-links a {
    background: none; border: none; padding: 0; cursor: pointer; font: inherit;
    color: var(--text-muted); text-decoration: none; font-size: 0.9rem; transition: color .15s;
}
.mkt-footer-links a:hover { color: var(--text-primary); }
.mkt-footer-bottom { margin-top: 28px; padding-top: 20px; border-top: 1px solid var(--border-soft); color: var(--text-muted); font-size: 0.82rem; display: flex; justify-content: space-between; flex-wrap: wrap; gap: 8px; }

/* ---- responsive ----------------------------------------------------------- */
@media (max-width: 1080px) {
    .mkt-cards-4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 860px) {
    .mkt-showcase { grid-template-columns: 1fr; }
    .mkt-cards { grid-template-columns: 1fr; }
    .mkt-cards-4 { grid-template-columns: repeat(2, 1fr); }
    .mkt-stats-grid { grid-template-columns: repeat(2, 1fr); }
    .mkt-gallery { grid-template-columns: repeat(2, 1fr); }
}
/* The bar is one row of brand + links + auth, and below roughly 780px that row
   is wider than the screen. It used to be held together by a
   .mkt-navlink-hide-sm rule that no markup ever carried, so nothing hid and the
   row simply ran off the right edge, taking the whole page into a sideways
   scroll. Wrapping is what actually holds: every part of the bar may wrap, so
   there is no width at which it can overflow again. */
@media (max-width: 780px) {
    .mkt-nav-row { flex-wrap: wrap; row-gap: 8px; justify-content: center; }
    .mkt-nav-links { flex-wrap: wrap; justify-content: center; gap: 6px 8px; }
    .mkt-nav-list { flex-wrap: wrap; justify-content: center; }
    /* Tighter link hit areas so the five of them make one row rather than two.
       The bar is sticky, so every row it takes is a row the page never gets. */
    .mkt-nav-links a.mkt-navlink,
    .mkt-nav .nav-menu-button.mkt-navlink { padding: 6px 8px; font-size: 0.85rem; }
}
@media (max-width: 560px) {
    .mkt-cards-4 { grid-template-columns: 1fr; }
    .mkt-nav { padding: 10px 0; }
    .mkt-wrap { padding: 0 16px; }
}
@media (prefers-reduced-motion: reduce) {
    .mkt-hero-video { display: none; }
    * { scroll-behavior: auto !important; }
}
