/* ============================================================
 * oddly landing archetypes. Design impl Phase 1b
 * (OEG-BRIEF-2026-DESIGNIMPL, design-handoff-2026-07-02).
 *
 * The reusable component layer behind the marketing surface. Phase 1
 * (#515) authored the landing's section archetypes INLINE in
 * src/app/index.html; the brief requires them as REUSABLE archetype
 * components so every other marketing page composes from the same set
 * instead of reinventing a look per page (the "cross-cutting visual
 * changes go through the shared layer, never stamped per page" rule,
 * locked 2026-06-23). This file lifts those archetypes verbatim out of
 * the landing into the shared layer, then adds the prose/longform
 * archetype family the narrative pages need, composed only from the
 * landing's own primitives (the same type scale, colours, hairlines,
 * radii, buttons). No new visual vocabulary.
 *
 * Built on the locked spine v2 tokens (/_shared/oddly-tokens.css:
 * Newsreader display serif, Hanken Grotesk body, cream canvas, teal is
 * the one action colour, gold is earned). Load order on a page:
 *   oddly-chrome.css, oddly-tokens.css, [insights.css], oddly-broadsheet.css,
 *   oddly-titan.css, then this.
 *
 * Section archetypes (from the landing, sections 1-9):
 *   hero + hero brief card, the idea (noise -> ranked), proof (ink inset),
 *   connectors grid, trust columns, manifesto, pricing cards, photo band,
 *   closing CTA panel.
 * Prose/longform archetypes (Phase 1b additions, composed from the above):
 *   band rhythm, longform prose column, solo prose hero, the gold-o seal,
 *   hairline fact rows, editorial table, question/answer FAQ.
 * ============================================================ */

.o-page {
  width: 100%;
  background: var(--oddly-canvas, #FAFAF7);
  color: var(--oddly-ink, #1A1A2E);
  font-family: var(--oddly-font-sans, "Hanken Grotesk", system-ui, sans-serif);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}
.o-page ::selection { background: var(--oddly-teal, #2C7873); color: var(--oddly-canvas, #FAFAF7); }

/* Shared display + emphasis primitives */
.o-serif { font-family: var(--oddly-font-serif, "Newsreader", Georgia, serif); font-weight: 400; }
.o-em { font-style: italic; color: var(--oddly-teal, #2C7873); }
.o-em-gold { font-style: italic; color: var(--oddly-gold, #B08D57); }
.o-kicker {
  font-size: 12px; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--oddly-teal, #2C7873); font-weight: 700;
}
.o-h2 {
  font-family: var(--oddly-font-serif, "Newsreader", Georgia, serif); font-weight: 400;
  font-size: clamp(32px, 4vw, 50px); line-height: 1.1; letter-spacing: -0.015em; margin: 0;
}
.o-sub { font-size: 19px; line-height: 1.6; color: var(--oddly-text-secondary, rgba(26,26,46,0.66)); margin: 0; }

/* Buttons (the reference's hero primary = the v2 button token defaults) */
.o-btn {
  display: inline-flex; align-items: center; gap: 10px; text-decoration: none;
  font-size: var(--oddly-btn-font-size, 16px); font-weight: var(--oddly-btn-weight, 600);
  padding: var(--oddly-btn-pad, 17px 30px); border-radius: var(--oddly-radius-btn, 11px);
}
.o-btn--teal { background: var(--oddly-teal, #2C7873); color: var(--oddly-canvas, #FAFAF7); }
.o-btn--ghost { color: var(--oddly-ink, #1A1A2E); }
.o-btn--outline { color: var(--oddly-ink, #1A1A2E); border: 1px solid var(--oddly-border-btn, rgba(26,26,46,0.18)); }

/* ---- Section 1: hero ---- */
.o-hero-sec { position: relative; background: var(--oddly-canvas, #FAFAF7); border-bottom: 1px solid var(--oddly-border-subtle, rgba(26,26,46,0.08)); overflow: hidden; }
.o-hero-glow { position: absolute; inset: 0; pointer-events: none; z-index: 0; overflow: hidden; }
.o-hero-glow::before {
  content: ""; position: absolute; top: -90px; right: -90px; width: 780px; height: 780px; border-radius: 50%;
  background: radial-gradient(circle at 50% 50%, var(--oddly-gold-tint-strong, rgba(176,141,87,0.14)), transparent 60%);
}
/* minmax(0, ...) on the second track is load-bearing. A bare `0.9fr` track takes
   its min-content as an automatic MINIMUM, so an oversized child (the hero
   product shot, which is deliberately wider than its column) expands the track
   and steals width from the copy column: the h1 lost its three-line break and
   wrapped to five with an orphaned word. minmax(0, 0.9fr) lets the track hold
   its fr size and the oversized child overflow it instead, which is what
   .o-hero-sec's overflow:hidden then clips. For any child that fits, this is
   identical to `0.9fr`. */
.o-hero { position: relative; z-index: 2; max-width: 1240px; margin: 0 auto; padding: 64px 44px 56px;
  display: grid; grid-template-columns: 1.1fr minmax(0, 0.9fr); gap: 60px; align-items: center; }
.o-hero-h1 {
  font-family: var(--oddly-font-serif, "Newsreader", Georgia, serif); font-weight: 400;
  font-size: clamp(44px, 5vw, 70px); line-height: 1.0; letter-spacing: -0.025em; margin: 26px 0; color: var(--oddly-ink, #1A1A2E);
}
.o-hero-sub { font-size: 20px; line-height: 1.55; color: var(--oddly-text-secondary, rgba(26,26,46,0.66)); max-width: 460px; margin: 0 0 36px; }
/* The two inline links in the hero paragraph had no rule anywhere, so they fell
   back to the browser's default link blue: a colour that is not in the palette,
   underlined in the UA style, sitting above the fold on the front door. They now
   follow the same convention as every other inline prose link (.o-prose a). */
.o-hero-sub a { color: var(--oddly-teal, #2C7873); font-weight: 600; text-decoration: none;
  border-bottom: 1px solid color-mix(in oklab, var(--oddly-teal, #2C7873) 40%, transparent); }
.o-hero-sub a:hover { border-bottom-color: var(--oddly-teal, #2C7873); }
.o-hero-cta { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.o-tour-ring { width: 30px; height: 30px; border-radius: 50%; border: 1px solid rgba(26,26,46,0.25); display: inline-flex; align-items: center; justify-content: center; font-size: 11px; }
/* The approve-first guarantee under the hero CTAs. Quiet on purpose: it is
   reassurance, not a third call to action. */
.o-hero-guard { display: flex; align-items: center; gap: 8px; margin: 20px 0 0; font-size: 14px;
  color: var(--oddly-text-secondary-soft, rgba(26,26,46,0.55)); }
.o-hero-guard-g { color: var(--oddly-teal, #2C7873); }

/* Hero product shot: a capture of the real Today view.
   It keeps the frame the hand-built mock wore (surface, subtle border, card
   radius, hero shadow, the teal-to-gold rule) so the brand language is
   unchanged and only the contents became real.
   The width is deliberately WIDER than the grid column it sits in. The right
   column resolves to about 490px at a 1240px hero, and a dashboard shrunk to
   490px is unreadable, which defeats the point of showing the product. So the
   shot renders at its legible size and bleeds off to the right; .o-hero-sec
   already sets overflow:hidden, so the bleed is clipped there and can never
   become page-level horizontal scroll. Below 900px the hero collapses to one
   column and the shot contains itself fully instead of bleeding. */
.o-hero-shot { justify-self: start; width: 780px; max-width: none; margin: 0;
  background: var(--oddly-surface, #FFF);
  border: 1px solid var(--oddly-border-subtle, rgba(26,26,46,0.08)); border-radius: var(--oddly-radius-card, 16px);
  box-shadow: var(--oddly-shadow-hero, 0 34px 70px -38px rgba(26,26,46,0.4)); overflow: hidden; }
.o-hero-shot picture { display: block; }
.o-hero-shot img { display: block; width: 100%; height: auto; }
/* The teal-to-gold rule the replaced hero card wore, kept as the shot's cap so
   the frame still reads as oddly rather than as a bare screenshot. */
.o-hero-shot-rule { height: 3px; background: linear-gradient(90deg, var(--oddly-teal, #2C7873), var(--oddly-gold, #B08D57)); }


/* ---- Section 1b: real-substrate trust bar (observed, not claimed) ----
 *
 * Kyle 2026-07-23, two notes on the same strip: the numbers read as big
 * figures a first-time visitor cannot weigh, and the type "doesn't look
 * entirely titan, feels like we're missing something".
 *
 * The second note had a concrete cause. This block carried its own near-miss
 * values for roles the broadsheet system already defines: an 11px/0.18em
 * eyebrow beside the system's 12px/0.16em `.flow-eyebrow`, a 13px label beside
 * `--fs-body-sm` 15px, a raw `--oddly-font-serif` beside `--serif`, and
 * `--oddly-text-secondary` beside the one body colour `--ink-body`. Each is
 * close enough to look intentional and wrong enough to read as off-system.
 * Every one of them is now the token, so the strip inherits the type scale
 * instead of approximating it.
 *
 * The first note is a structure change, not a size change: a figure above a
 * label states a quantity but never says what it BUYS the reader. The figure
 * now leads a sentence and the sentence names the consequence, so the numeral
 * is read as the subject of a claim rather than as a headline on its own. */
.o-tb-sec { max-width: 1240px; margin: 0 auto; padding: 24px 44px 30px; }
.o-tb {
  display: flex; align-items: flex-start; gap: clamp(18px, 3.5vw, 48px); flex-wrap: wrap;
  padding-top: 22px; border-top: 1px solid var(--line, rgba(26,26,46,0.08));
}
/* The eyebrow is `.flow-eyebrow`; this only clears its bottom margin so it sits
 * on the same baseline as the proof lines beside it. */
.o-tb-label { margin: 0; flex: 0 0 auto; }
.o-tb-stats {
  /* Three proof lines, each a sentence, so they need column width rather than
   * the tight baseline row a number-plus-label strip wanted. auto-fit means a
   * line hidden by honest-null simply gives its width back to the others. */
  display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: clamp(16px, 2.4vw, 34px);
  flex: 1 1 420px; margin: 0; padding: 0; list-style: none;
}
.o-tb-stat[hidden] { display: none; }
.o-tb-line {
  margin: 0;
  font-family: var(--sans, inherit);
  font-size: var(--fs-body-sm, 15px);
  line-height: 1.5;
  color: var(--ink-body, rgba(26,26,46,0.66));
  text-wrap: pretty;
}
/* The figure leads its sentence: serif, one step up, sitting on the same
 * baseline as the words that follow it. Not a display number, deliberately.
 * Making it larger again would restore exactly the imbalance Kyle flagged. */
.o-tb-num {
  font-family: var(--serif, "Newsreader", Georgia, serif); font-weight: 400;
  font-size: 22px; line-height: 1; letter-spacing: -0.01em;
  color: var(--ink-display, #1A1A2E);
  margin-right: 3px;
}
.o-tb-num--teal { color: var(--teal, #2C7873); }
.o-tb-link {
  align-self: center;
  font-size: var(--fs-body-sm, 15px); font-weight: 600;
  color: var(--teal, #2C7873); text-decoration: none;
  border-bottom: 1px solid color-mix(in oklab, var(--teal, #2C7873) 40%, transparent);
  margin-left: auto;
}
/* Hover and focus both raise contrast rather than only tinting: the rest state
 * is a 40% hairline, so darkening it to full teal is a real change, not a
 * hover-coloured guess. :focus-visible (not :focus) so a mouse click does not
 * leave a ring behind. */
.o-tb-link:hover { border-bottom-color: var(--teal, #2C7873); }
.o-tb-link:focus-visible {
  outline: 2px solid var(--teal, #2C7873);
  outline-offset: 3px;
  border-radius: 2px;
}
@media (max-width: 700px) {
  .o-tb-sec { padding: 24px 22px 30px; }
  .o-tb { gap: 16px; }
  /* One sentence per row on a phone: two narrow columns would break the lines
   * into ragged fragments and the consequence clause is the whole point. */
  .o-tb-stats { grid-template-columns: 1fr; gap: 14px; flex-basis: 100%; }
  .o-tb-link { margin-left: 0; align-self: flex-start; }
}

/* ---- Section 2: the idea ---- */
.o-idea-sec { max-width: 1200px; margin: 0 auto; padding: 70px 40px 120px; }
.o-idea-intro { max-width: 760px; margin-bottom: 64px; }
.o-idea-intro .o-h2 { margin-bottom: 22px; }
.o-idea { display: grid; grid-template-columns: 1fr auto 1.1fr; gap: 48px; align-items: center;
  background: var(--oddly-surface, #FFF); border: 1px solid var(--oddly-border-subtle, rgba(26,26,46,0.08)); border-radius: var(--oddly-radius-card-lg, 20px); padding: 48px; }
.o-idea-k { font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--oddly-text-tertiary-soft, rgba(26,26,46,0.4)); font-weight: 600; margin-bottom: 18px; }
.o-chips { display: flex; flex-wrap: wrap; gap: 9px; }
.o-chip { font-size: 13px; padding: 7px 13px; border-radius: 30px; background: rgba(26,26,46,0.04); color: var(--oddly-text-secondary-soft, rgba(26,26,46,0.55)); }
.o-idea-arrow { display: flex; flex-direction: column; align-items: center; gap: 8px; color: var(--oddly-teal, #2C7873); }
.o-idea-arrow-l { font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; font-weight: 600; }
.o-idea-arrow-g { font-size: 30px; }
.o-rank { display: flex; flex-direction: column; gap: 12px; }
.o-rank-row { display: flex; align-items: center; gap: 14px; padding: 16px 18px; border-radius: 12px; border: 1px solid rgba(26,26,46,0.1); }
.o-rank-row--hi { border: 1px solid var(--oddly-teal-tint-strong, rgba(44,120,115,0.25)); background: var(--oddly-teal-tint-faint, rgba(44,120,115,0.04)); }
.o-rank-num { width: 28px; height: 28px; border-radius: 50%; color: var(--oddly-canvas, #FAFAF7); font-weight: 700; font-size: 14px; text-align: center; line-height: 28px; }
.o-rank-t { flex: 1; font-size: 15px; font-weight: 600; }
.o-rank-tag { font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; font-weight: 700; }

/* ---- Section 3: proof (ink inset) ---- */
.o-proof-sec { background: var(--oddly-canvas, #FAFAF7); padding: 44px 24px 64px; }
.o-proof-panel { max-width: 1240px; margin: 0 auto; padding: clamp(48px, 6vw, 92px) clamp(24px, 5vw, 60px); background: var(--oddly-ink, #1A1A2E); color: var(--oddly-canvas, #FAFAF7); border-radius: var(--oddly-radius-inset, 30px); }
.o-proof-head { max-width: 720px; margin-bottom: 56px; }
.o-proof-head .o-h2 { margin-bottom: 22px; }
.o-proof-head p { font-size: 19px; line-height: 1.6; color: rgba(250,250,247,0.66); margin: 0; }
.o-proof-mock { box-shadow: var(--oddly-shadow-proof, 0 50px 110px -40px rgba(0,0,0,0.6)); border-radius: 20px; overflow: hidden; }
.o-proof-mock a { text-decoration: none; color: inherit; display: block; }

/* ---- Section 4: connectors ---- */
.o-conn-sec { max-width: 1120px; margin: 0 auto; padding: 80px 40px 72px; }
.o-conn-intro { text-align: center; max-width: 720px; margin: 0 auto 52px; }
.o-conn-intro .o-h2 { font-size: clamp(30px, 3.6vw, 46px); line-height: 1.12; margin-bottom: 20px; }
.o-conn-intro p { font-size: 18px; line-height: 1.6; color: var(--oddly-text-secondary, rgba(26,26,46,0.64)); margin: 0; }
.o-grid4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: rgba(26,26,46,0.1); border: 1px solid rgba(26,26,46,0.1); border-radius: var(--oddly-radius-card, 16px); overflow: hidden; }
.o-conn-cell { background: var(--oddly-surface, #FFF); padding: 26px 24px; }
.o-conn-k { font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--oddly-teal, #2C7873); font-weight: 700; margin-bottom: 18px; }
.o-conn-items { display: flex; flex-direction: column; gap: 11px; }
.o-conn-on { font-size: 15px; font-weight: 600; color: var(--oddly-ink, #1A1A2E); }
.o-conn-soon { font-size: 14px; color: var(--oddly-text-tertiary, rgba(26,26,46,0.5)); }
.o-conn-foot { text-align: center; margin-top: 26px; font-size: 14px; color: var(--oddly-text-tertiary, rgba(26,26,46,0.5)); }

/* ---- Section 5: trust ---- */
.o-trust-sec { max-width: 1200px; margin: 0 auto; padding: 40px 40px 100px; }
.o-trust-head { max-width: 720px; margin-bottom: 56px; }
.o-trust-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 36px; }
.o-trust-col { padding-top: 22px; }
.o-trust-col--teal { border-top: 2px solid var(--oddly-teal, #2C7873); }
.o-trust-col--gold { border-top: 2px solid var(--oddly-gold, #B08D57); }
.o-trust-t { font-size: 17px; font-weight: 700; margin-bottom: 10px; }
.o-trust-col p { font-size: 14px; line-height: 1.6; color: var(--oddly-text-secondary, rgba(26,26,46,0.6)); margin: 0; }
/* On the ink band, the trust columns keep their teal/gold top-rule accent but
   flip to light text (the page's one ink "moment"). */
.o-band--ink .o-trust-t { color: var(--oddly-canvas, #FAFAF7); }
.o-band--ink .o-trust-col p { color: rgba(250,250,247,0.72); }

/* ---- Section 6: manifesto ---- */
.o-manifesto { max-width: 880px; margin: 0 auto; padding: 72px 40px 100px; text-align: center; }
.o-manifesto-h { font-family: var(--oddly-font-serif, "Newsreader", serif); font-weight: 400; font-size: clamp(30px, 3.8vw, 48px); line-height: 1.16; letter-spacing: -0.015em; color: var(--oddly-ink, #1A1A2E); margin: 0 0 26px; }
.o-manifesto p.sub { font-size: 18px; line-height: 1.65; color: var(--oddly-text-secondary, rgba(26,26,46,0.62)); max-width: 620px; margin: 0 auto; }

/* ---- Section 7: pricing ---- */
.o-pricing-sec { background: var(--oddly-canvas, #FAFAF7); }
.o-pricing { max-width: 1200px; margin: 0 auto; padding: 110px 40px 120px; }
.o-pricing-head { max-width: 720px; margin-bottom: 56px; }
.o-pricing-head .o-h2 { margin-bottom: 22px; }
.o-grid3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; align-items: stretch; }
/* Four-rung tier ladder (Watch / Spark / Nudge / Autopilot). Same o-tier
   cards, one more column with a tighter gutter; collapses to 2-up then 1-up. */
.o-grid4-tier { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; align-items: stretch; }
.o-tier { border-radius: 18px; padding: 32px; display: flex; flex-direction: column; }
.o-tier--plain { background: var(--oddly-canvas, #FAFAF7); border: 1px solid rgba(26,26,46,0.1); }
.o-tier--feat { background: var(--oddly-canvas, #FAFAF7); border: 1px solid rgba(44,120,115,0.4); position: relative; box-shadow: var(--oddly-shadow-cta, 0 24px 50px -30px rgba(44,120,115,0.5)); }
.o-tier--dark { background: var(--oddly-ink, #1A1A2E); color: var(--oddly-canvas, #FAFAF7); }
.o-tier-badge { position: absolute; top: -11px; left: 32px; background: var(--oddly-teal, #2C7873); color: var(--oddly-canvas, #FAFAF7); font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; font-weight: 700; padding: 5px 12px; border-radius: 30px; }
.o-tier-name { font-family: var(--oddly-font-serif, "Newsreader", serif); font-weight: 400; font-size: 24px; margin-bottom: 6px; }
.o-tier-head { display: flex; align-items: center; justify-content: space-between; }
.o-tier-req { font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; font-weight: 700; color: var(--oddly-gold, #B08D57); }
.o-tier-tag { font-size: 14px; color: rgba(26,26,46,0.55); margin-bottom: 22px; }
.o-tier--dark .o-tier-tag { color: rgba(250,250,247,0.55); }
.o-tier-price { display: flex; align-items: baseline; gap: 6px; margin-bottom: 24px; }
.o-tier-price b { font-size: 36px; font-weight: 700; letter-spacing: -0.01em; }
.o-tier-price span { font-size: 15px; color: rgba(26,26,46,0.45); }
.o-tier-price--prem b { font-size: 30px; color: var(--oddly-gold, #B08D57); }
.o-tier-feats { display: flex; flex-direction: column; gap: 12px; margin-bottom: 28px; font-size: 14px; color: rgba(26,26,46,0.7); }
.o-tier--dark .o-tier-feats { color: rgba(250,250,247,0.78); }
.o-tier-feat { display: flex; gap: 10px; }
.o-tier-check { color: var(--oddly-teal, #2C7873); font-weight: 700; }
.o-tier--dark .o-tier-check { color: var(--oddly-gold, #B08D57); }
.o-tier-cta { margin-top: auto; text-align: center; padding: 14px; border-radius: var(--oddly-radius-btn, 11px); font-size: 15px; font-weight: 600; text-decoration: none; }
.o-tier-cta--ghost { border: 1px solid rgba(26,26,46,0.18); color: var(--oddly-ink, #1A1A2E); }
.o-tier-note { margin-top: 10px; font-size: 12.5px; color: rgba(26,26,46,0.55); text-align: center; }
.o-tier-cta--teal { background: var(--oddly-teal, #2C7873); color: var(--oddly-canvas, #FAFAF7); }
.o-tier-cta--dark { border: 1px solid rgba(250,250,247,0.25); color: var(--oddly-canvas, #FAFAF7); }
.o-pricing-foot { text-align: center; margin-top: 30px; font-size: 14px; color: var(--oddly-text-tertiary, rgba(26,26,46,0.5)); }

/* ---- Section 8: anywhere band ---- */
.o-anywhere-sec { background: var(--oddly-canvas, #FAFAF7); padding: 44px 24px; }
.o-anywhere { position: relative; max-width: 1240px; margin: 0 auto; border-radius: var(--oddly-radius-inset, 30px); overflow: hidden; }
.o-stage-wrap { position: relative; width: 100%; aspect-ratio: 1024 / 576; overflow: hidden; }
.o-stage { position: absolute; top: 0; left: 0; width: 1024px; height: 576px; transform-origin: top left; }
.o-stage img.o-cafe { display: block; width: 1024px; height: 576px; }
.o-scrim { position: absolute; inset: 0; background: linear-gradient(90deg, rgba(250,250,247,0.94) 0%, rgba(250,250,247,0.72) 22%, rgba(250,250,247,0) 46%); }
/* Laptop-screen composite. The perspective transform is final. The FILL used to be
   a "TEMP neutral placeholder until the Playwright dashboard-render row supplies a
   real screenshot", written 2026-07-03: a blank card carrying only the wordmark, on
   a laptop, in a section headed "The whole store, on one calm screen". That is the
   product's own shop window showing a blank screen, which is the same defect #831
   was built to kill on the hero, and the row it was waiting for is exactly the
   capture script #831 shipped. Closed here with `node scripts/hero-capture.mjs`
   output (the anywhere-screen shot): the real v2 Today view, rendered locally
   against stubbed endpoints so the figures are demo by construction and no real
   merchant's revenue lands on the public landing page.

   The image is placed with object-fit: cover from the top-left so the crop is the
   top of the view (the score, the play, the comparison), which is what a laptop lid
   actually shows, and so a re-capture at a different height cannot letterbox. */
/* 772x540, not the original 800x560. The transform-origin is the top-left, so
   trimming width and height pulls the right and bottom edges in while the
   registered top-left corner stays put. The 800x560 box overhung the laptop's
   right bezel and spilled below the lid onto the keyboard, which nobody could see
   while the fill was a soft gradient behind a scrim: a gradient has no edge to
   catch on the bezel. A real screenshot does, so the misfit only became visible
   the moment the placeholder went away. Found by rendering and looking, then
   fitted empirically against the photo (800, 772, 748, 726 rendered side by side;
   772 is the largest that keeps the bezel visible on every edge). */
/* The compositing pass (recipe: docs/design/device-composite-recipe.md).
   Everything below is in the SCREEN's own coordinate space and rides the
   matrix3d, so a radius, a sheen and a bezel shadow land on the lid plane rather
   than on the page plane. That is why they are on this element and not on a
   wrapper. Before this pass the panel was a hard-cornered, cold-neutral rectangle
   on a warm golden-hour plate, which is the single most visible reason a
   composite reads as pasted. */
.o-screen { position: absolute; top: 0; left: 0; width: 772px; height: 540px;
  transform: matrix3d(0.39772,-0.00563,0,-0.000092,-0.010936,0.459372,0,0.00001,0,0,1,0,527,150,0,1); transform-origin: 0 0;
  background: var(--oddly-surface, #FFF);
  /* (b) corner radius. Generous in screen space because the plane is displayed at
     roughly 0.4x: 14px here reads as the ~5px radius a real lid shows. */
  border-radius: 14px;
  overflow: hidden; }
/* (d) colour temperature and exposure. The plate is lit warm; a screenshot is
   not. A light sepia plus a touch off full brightness is enough to seat it, and
   is kept small on purpose: past about 0.12 the teal CTA starts turning olive. */
.o-screen img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: top left;
  filter: sepia(0.09) saturate(1.04) contrast(1.02) brightness(0.975); }
/* (d) again as a graded wash, and (e) the bezel integration: an inner shadow at
   the panel edge plus a hairline, so the screen sits INSIDE the lid instead of
   on top of it. Warm at the light source (upper left, per the plate), cooling
   across to the shadowed right. */
.o-screen::before { content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  border-radius: inherit;
  background: linear-gradient(114deg, rgba(255,206,138,0.17) 0%, rgba(255,201,143,0.07) 44%, rgba(96,116,150,0.06) 100%);
  box-shadow:
    inset 0 0 0 1px rgba(38,28,16,0.20),
    inset 0 12px 26px -12px rgba(44,30,12,0.42),
    inset 0 -10px 20px -12px rgba(44,30,12,0.26),
    inset 14px 0 26px -18px rgba(44,30,12,0.30); }
/* (c) screen-space sheen. A single soft diagonal band, screen-blended so it lifts
   the panel without washing the type: the difference between glass and a sticker
   is a highlight that does not belong to the content. */
.o-screen::after { content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none;
  border-radius: inherit; mix-blend-mode: screen;
  background: linear-gradient(102deg,
    rgba(255,255,255,0.34) 0%,
    rgba(255,255,255,0.13) 15%,
    rgba(255,255,255,0.02) 31%,
    rgba(255,255,255,0) 62%,
    rgba(255,255,255,0.09) 100%); }
.o-anywhere-copy { position: absolute; top: 50%; left: 6%; transform: translateY(-50%); width: 34%; min-width: 260px; z-index: 3; }
.o-anywhere-copy h2 { font-family: var(--oddly-font-serif, "Newsreader", serif); font-weight: 400; font-size: clamp(28px, 3.4vw, 46px); line-height: 1.06; letter-spacing: -0.02em; margin: 0 0 18px; }
.o-anywhere-copy p { font-size: 17px; line-height: 1.55; color: var(--oddly-text-secondary, rgba(26,26,46,0.66)); margin: 0; }
.o-anywhere-copy .o-kicker { display: block; margin-bottom: 20px; }

/* ---- Section 9: closing ---- */
.o-close-sec { background: var(--oddly-canvas, #FAFAF7); padding: 44px 24px 72px; }
.o-close-panel { position: relative; max-width: 1240px; margin: 0 auto; border-radius: var(--oddly-radius-inset, 30px); overflow: hidden; background-image: url('/site/desk-book.png'); background-size: cover; background-position: center; }
.o-close-veil { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(250,250,247,0.9), rgba(250,250,247,0.82)); }
.o-close-body { position: relative; z-index: 2; max-width: 820px; margin: 0 auto; padding: clamp(72px, 9vw, 112px) 40px; text-align: center; }
.o-close-h { font-family: var(--oddly-font-serif, "Newsreader", serif); font-weight: 400; font-size: clamp(38px, 5vw, 66px); line-height: 1.05; letter-spacing: -0.02em; margin: 0 0 24px; }
.o-close-sub { font-size: 20px; line-height: 1.6; color: var(--oddly-text-secondary, rgba(26,26,46,0.68)); max-width: 560px; margin: 0 auto 40px; }
.o-close-cta { display: flex; align-items: center; justify-content: center; gap: 16px; flex-wrap: wrap; }
.o-close-cta .o-btn { padding: 18px 34px; border-radius: 12px; font-size: 17px; }
.o-close-cta .o-btn--outline { padding: 18px 26px; }
.o-close-foot { margin-top: 22px; font-size: 14px; color: var(--oddly-text-tertiary, rgba(26,26,46,0.5)); }

/* ============================================================
 * PROSE / LONGFORM ARCHETYPE FAMILY (Phase 1b).
 *
 * The narrative marketing pages (what-is-oddly, why-oddly,
 * how-it-works, ...) are editorial: measured prose columns broken by
 * the section archetypes above. These classes give them one band
 * rhythm and one prose voice, composed only from the landing's
 * primitives and the spine v2 tokens. Nothing here introduces a colour,
 * type family, radius, or shadow the landing does not already use.
 * ============================================================ */

/* Band rhythm: alternating fields with a centred wrap. The one place
   the marketing surface sets its vertical breathing + field colours. */
.o-band { padding: var(--oddly-section-y, clamp(72px, 9vw, 120px)) 0; background: var(--oddly-canvas, #FAFAF7); }
.o-band--surface { background: var(--oddly-surface, #FFF); }
.o-band--sunken { background: var(--oddly-surface-sunken, #F4F2EC); }
.o-band--ink { background: var(--oddly-ink, #1A1A2E); color: var(--oddly-canvas, #FAFAF7); }
.o-band--hero { padding: 72px 0 60px; border-bottom: 1px solid var(--oddly-border-subtle, rgba(26,26,46,0.08)); position: relative; overflow: hidden; }
.o-band--hero .o-wrap { position: relative; z-index: 2; }
.o-wrap { max-width: var(--oddly-max-landing, 1240px); margin: 0 auto; padding: 0 var(--oddly-pad-x-wide, 44px); }
.o-measure { max-width: 760px; }

/* Longform prose: a bare Newsreader serif heading + Hanken body at the
   landing's reading size, in a measured column. The narrative pages carry
   test-locked BARE headings (<h1>/<h2>/<h3> that mirror schema), so the
   prose family styles bare headings inside its containers rather than
   requiring a class. Same serif, sizes, colours as the landing's o-h2.
   Ink emphasis, teal links. */
.o-prose h2 {
  font-family: var(--oddly-font-serif, "Newsreader", Georgia, serif); font-weight: 400;
  font-size: clamp(28px, 3.2vw, 40px); line-height: 1.12; letter-spacing: -0.015em;
  color: var(--oddly-ink, #1A1A2E); margin: 0 0 22px; max-width: 20em;
}
.o-prose > p { font-size: var(--oddly-landing-body, 18px); line-height: 1.65; color: var(--oddly-text-secondary, rgba(26,26,46,0.7)); margin: 0 0 18px; }
.o-prose > p:last-child { margin-bottom: 0; }
.o-prose p strong { color: var(--oddly-ink, #1A1A2E); font-weight: 600; }
.o-prose a:not(.o-btn) { color: var(--oddly-teal, #2C7873); font-weight: 600; text-decoration: none; }
.o-prose a:not(.o-btn):hover { text-decoration: underline; }
.o-band--ink .o-prose h2 { color: var(--oddly-canvas, #FAFAF7); }
.o-band--ink .o-prose > p { color: rgba(250,250,247,0.72); }
.o-band--ink .o-prose p strong { color: var(--oddly-canvas, #FAFAF7); }
.o-band--ink .o-prose a:not(.o-btn) { color: var(--oddly-gold, #B08D57); }
.o-lede { font-size: clamp(19px, 2vw, 22px); line-height: 1.5; color: var(--oddly-ink, #1A1A2E); max-width: 34em; margin: 0 0 26px; }
/* Same gap as .o-hero-sub had: a lede outside .o-prose gets no inline-link rule,
   so its links rendered in the browser's default blue. /platform carried three of
   them, and /platform is where the hero's "accountability layer" link sends a
   first-time visitor. */
.o-lede a:not(.o-btn) { color: var(--oddly-teal, #2C7873); font-weight: 600; text-decoration: none;
  border-bottom: 1px solid color-mix(in oklab, var(--oddly-teal, #2C7873) 40%, transparent); }
.o-lede a:not(.o-btn):hover { border-bottom-color: var(--oddly-teal, #2C7873); }

/* Solo prose hero: the landing hero display treatment on a single column
   (no brief card), for pages whose hero is a sentence, not a screenshot.
   The bare test-locked <h1> gets the display face. */
.o-hero-prose h1 {
  font-family: var(--oddly-font-serif, "Newsreader", Georgia, serif); font-weight: 400;
  font-size: clamp(40px, 5vw, 64px); line-height: 1.02; letter-spacing: -0.025em;
  color: var(--oddly-ink, #1A1A2E); margin: 20px 0 22px; max-width: 15em;
}

/* The gold-o seal: the one-line promise, gold "o" + Newsreader. */
.o-seal {
  display: inline-flex; align-items: center; gap: 12px;
  font-family: var(--oddly-font-serif, "Newsreader", serif); font-size: 17px; color: var(--oddly-ink, #1A1A2E);
  border: 1px solid var(--oddly-border-subtle, rgba(26,26,46,0.08)); background: rgba(255,255,255,0.55);
  border-radius: var(--oddly-radius-btn, 11px); padding: 11px 18px; margin: 0 0 28px;
}
.o-seal-o {
  font-family: var(--oddly-font-serif, "Newsreader", serif); font-weight: 600; font-size: 22px;
  color: var(--oddly-gold, #B08D57); display: inline-block;
  transform: rotate(5deg); transform-origin: 50% 60%;
}
.o-hero-cta--wrap { display: flex; flex-wrap: wrap; gap: 14px; }

/* Hairline fact rows: the connectors/works-with/signals list, one
   hairline-separated stack. */
.o-factrow {
  list-style: none; margin: 8px 0 0; padding: 0;
  display: grid; gap: 1px;
  background: var(--oddly-border-subtle, rgba(26,26,46,0.08)); border: 1px solid var(--oddly-border-subtle, rgba(26,26,46,0.08));
  border-radius: var(--oddly-radius-card-sm, 14px); overflow: hidden;
}
.o-factrow li { background: var(--oddly-surface, #FFF); padding: 15px 18px; font-size: 15px; line-height: 1.55; color: var(--oddly-text-secondary, rgba(26,26,46,0.7)); }
.o-band--sunken .o-factrow li { background: var(--oddly-surface-sunken, #F4F2EC); }
.o-factrow li strong { color: var(--oddly-ink, #1A1A2E); font-weight: 600; }

/* Editorial table: sharp field, hairline rules, tabular numerals,
   scrolls on narrow screens. */
.o-tablewrap { overflow-x: auto; margin: 8px 0 0; border: 1px solid var(--oddly-border-subtle, rgba(26,26,46,0.08)); border-radius: var(--oddly-radius-card-sm, 14px); }
.o-table { width: 100%; border-collapse: collapse; font-size: 14px; min-width: 560px; }
.o-table th, .o-table td { text-align: left; padding: 12px 15px; border-bottom: 1px solid var(--oddly-border-subtle, rgba(26,26,46,0.08)); vertical-align: top; }
.o-table thead th { background: var(--oddly-surface-sunken, #F4F2EC); font-weight: 700; color: var(--oddly-ink, #1A1A2E); white-space: nowrap; }
.o-table thead th.o-col-oddly { color: var(--oddly-teal, #2C7873); }
.o-table tbody tr:last-child td { border-bottom: none; }
.o-table td.o-price { font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums; }
.o-table td.o-cell-yes { font-weight: 600; color: var(--oddly-teal, #2C7873); }
.o-table td.o-cell-no { color: var(--oddly-text-secondary, rgba(26,26,46,0.66)); }
.o-tablenote { font-size: 14px; color: var(--oddly-text-secondary, rgba(26,26,46,0.66)); margin-top: 14px; }
.o-tablenote a { color: var(--oddly-teal, #2C7873); font-weight: 600; }

/* Question/answer FAQ: bare H3 questions (test-locked, mirror the
   FAQPage schema) + measured answers. */
.o-faq h3 {
  font-family: var(--oddly-font-serif, "Newsreader", serif); font-size: 20px; font-weight: 400;
  letter-spacing: -0.01em; color: var(--oddly-ink, #1A1A2E); margin: 30px 0 8px;
}
.o-faq h3:first-of-type { margin-top: 8px; }
.o-faq p { margin: 0 0 8px; font-size: 16px; line-height: 1.6; color: var(--oddly-text-secondary, rgba(26,26,46,0.7)); }

/* ---- responsive (handoff breakpoints) ---- */
@media (max-width: 900px) {
  .o-hero { grid-template-columns: 1fr; gap: 40px; padding-top: 48px; }
  .o-hero-card { justify-self: stretch; max-width: 460px; }
  /* One column: the shot stops bleeding and fits the measure instead. */
  .o-hero-shot { justify-self: stretch; width: 100%; max-width: 620px; }
  .o-idea { grid-template-columns: 1fr; gap: 26px; padding: 32px; }
  .o-idea-arrow-g { transform: rotate(90deg); }
  .o-grid4 { grid-template-columns: repeat(2, 1fr); }
  .o-trust-grid { grid-template-columns: repeat(2, 1fr); }
  .o-grid3 { grid-template-columns: 1fr; max-width: 420px; margin-left: auto; margin-right: auto; }
  .o-grid4-tier { grid-template-columns: repeat(2, 1fr); }
  .o-anywhere { display: flex; flex-direction: column-reverse; gap: 24px; }
  /* The 30px radius plus overflow:hidden belongs to the IMAGE, not to the stacked
     flex container. Left on the container it clipped the first letter of the
     kicker: at mobile the copy becomes the top-left child, so "RUN IT FROM
     ANYWHERE" rendered with the R sliced off by the corner curve. Found by
     rendering at 390, not by reading the CSS. The rounding moves down to the
     stage so the photo still has soft corners and the copy has straight ones. */
  .o-anywhere { overflow: visible; border-radius: 0; }
  .o-stage-wrap { border-radius: var(--oddly-radius-inset, 30px); }
  .o-anywhere-copy { position: static; transform: none; width: auto; min-width: 0; left: auto; top: auto; padding: 0 4px 8px; }
}
@media (max-width: 560px) {
  .o-grid4 { grid-template-columns: 1fr; }
  .o-grid4-tier { grid-template-columns: 1fr; max-width: 420px; margin-left: auto; margin-right: auto; }
  .o-trust-grid { grid-template-columns: 1fr; }
  .o-hero, .o-idea-sec, .o-trust-sec, .o-pricing, .o-manifesto, .o-conn-sec { padding-left: 22px; padding-right: 22px; }
  .o-wrap { padding-left: 22px; padding-right: 22px; }
  .o-band { padding: 56px 0; }
  .o-band--hero { padding: 52px 0 44px; }
}
