/* HogLens — design foundation. ONE colour scheme: LIGHT, ALWAYS.
   Decided by Patrick on 2026-09-04 (ADR-H3 amendment): the product screenshots are
   light captures, and a dark page around light shots reads as a mistake. The site does
   NOT follow prefers-color-scheme — every visitor gets this palette. This diverges from
   the brief ("dark mode default") and from the PladioWeb precedent, on purpose.

   Palette derived from the app ICON (the asset catalog defines no colours, ADR-H3).

   Tokens validated for WCAG AA — measured 2026-09-04 with docs-dev/contrast.py over
   every pair this stylesheet can produce (output pasted verbatim into ADR-H3); re-run it
   when touching any token:
     ink on bg                14.61:1  ·  ink on raised            15.58:1
     muted on bg               5.09:1  ·  muted on raised           5.43:1
     accent-text on bg         5.77:1  ·  accent-text on raised     6.15:1
     on-blue ink on hl-blue    8.56:1  ·  ink on hero tint         13.52:1
     muted on hero tint        4.71:1  ·  accent-text on hero tint  5.34:1

   Two traps:
   1. WHITE ON THE BRAND BLUE IS 1.82:1. Buttons, badges and glyph tiles use --on-blue
      (the navy ink) at 8.56:1. Never white.
   2. --hl-blue (#97C4F5) is a FILL. As text on this page it is 1.71:1. Text that wants
      the brand colour uses --accent-text. Never "unify" the two. */
:root {
    /* Brand — sampled from the icon */
    --hl-blue: #97C4F5;          /* icon background gradient, lower half — FILL ONLY */
    --hl-rose: #D6AAAB;          /* hedgehog body — decorative only, never text */

    /* Text on brand-blue fills (buttons, glyph tiles, badges) — 8.56:1 */
    --on-blue: #16243A;

    /* Link / kicker text — a darkened lens blue, 5.77:1 on bg, 6.15:1 on raised */
    --accent-text: #2B62A8;

    /* Neutrals: the icon's top gradient tinted, navy ink from the wordmark */
    --bg: #F4F8FD;
    --bg-raised: #FFFFFF;
    --ink: #16243A;
    --ink-muted: #5B6B82;
    --line: rgba(22, 36, 58, 0.12);
    --hero-tint: #E6F0FB;        /* between the icon gradient midtone and white; muted text clears AA on it */

    /* Type — rounded display via ui-rounded (renders SF Pro Rounded on Apple
       devices). Zero font bytes; the CSP forbids font CDNs. */
    --font-display: ui-rounded, -apple-system, "SF Pro Rounded", system-ui, sans-serif;
    --font-body: -apple-system, BlinkMacSystemFont, system-ui, "Segoe UI", Roboto, sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;

    /* Spacing scale */
    --s-1: 0.25rem;
    --s-2: 0.5rem;
    --s-3: 0.75rem;
    --s-4: 1rem;
    --s-5: 1.5rem;
    --s-6: 2rem;
    --s-7: 3rem;
    --s-8: 4.5rem;
    --s-9: 7rem;
    --radius: 14px;
    --radius-lg: 24px;
    --measure: 42rem;
    --page-max: 68rem;
    /* Light always: form controls and scrollbars follow the page, not the OS setting. */
    color-scheme: light;
}

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

html {
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    background: var(--bg);
    color: var(--ink);
    font-family: var(--font-body);
    font-size: 1.0625rem;
    line-height: 1.6;
}

h1,
h2,
h3 {
    font-family: var(--font-display);
    line-height: 1.15;
    letter-spacing: -0.015em;
    margin: 0 0 var(--s-4);
}

h1 {
    font-size: clamp(2.4rem, 6.5vw, 4rem);
    font-weight: 800;
}

h2 {
    font-size: clamp(1.7rem, 4vw, 2.4rem);
    font-weight: 700;
}

h3 {
    font-size: 1.2rem;
    font-weight: 700;
}

p {
    margin: 0 0 var(--s-4);
}

a {
    color: var(--accent-text);
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
}

code {
    font-family: var(--font-mono);
    font-size: 0.92em;
}

/* Touch targets for links set mid-sentence. These render 18–20px tall, under
   WCAG 2.5.8's 24px — but 2.5.8 exempts inline text, so this is comfort on a
   phone rather than a conformance fix. Vertical padding on an inline box grows
   the hit area without touching the line box. Do NOT raise these toward 44px:
   the boxes on adjacent wrapped lines would overlap and the upper link would win
   hit-testing. */
.legal p a,
.legal li a,
.faq details p a {
    padding-block: 2px;   /* 20px content in a 27px line box -> 24px */
}

.legal .portal-fallback a,
.site-footer p a {
    padding-block: 3px;   /* 18px content in a 24px line box -> 24px */
}

a:hover {
    text-decoration-thickness: 2px;
}

img,
svg {
    max-width: 100%;
    height: auto;
}

:focus-visible {
    outline: 3px solid var(--accent-text);
    outline-offset: 2px;
    border-radius: 4px;
}

.wrap {
    max-width: var(--page-max);
    margin-inline: auto;
    padding-inline: var(--s-5);
}

.measure {
    max-width: var(--measure);
}

.measure-center {
    margin-inline: auto;
}

.skip-link {
    position: absolute;
    left: -999px;
    top: var(--s-2);
    background: var(--ink);
    color: var(--bg);
    padding: var(--s-2) var(--s-4);
    border-radius: 999px;
    z-index: 20;
    display: inline-flex;
    align-items: center;
    min-height: 44px;   /* keyboard-only, but a target is a target (WCAG 2.5.8) */
}

.skip-link:focus {
    left: var(--s-2);
}

/* ---------- Justified prose ----------
   Inherited from PladioWeb's site-wide decision (2026-09-03); hyphens: auto keeps rivers
   down (every page declares lang="en"). The hero stays centred. Drop this block if
   Patrick prefers ragged-right for HogLens — it is one rule, not a system. */
main p,
main li,
.site-footer p {
    text-align: justify;
    hyphens: auto;
}

.hero h1,
.hero p {
    text-align: center;
}

/* ---------- Header ---------- */
.site-header {
    border-bottom: 1px solid var(--line);
    padding-block: var(--s-4);
}

.site-header .wrap {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-4);
}

.wordmark {
    display: inline-flex;
    align-items: center;
    gap: var(--s-3);
    color: var(--ink);
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.15rem;
    text-decoration: none;
    min-height: 44px;   /* 44px target */
}

.wordmark img {
    border-radius: 8px;
}

/* ---------- Buttons & CTA ---------- */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--s-2);
    min-height: 48px;
    padding: var(--s-3) var(--s-5);
    border-radius: 999px;
    background: var(--hl-blue);
    color: var(--on-blue);   /* 8.56:1. White here is 1.82:1 and fails — see the header comment. */
    font-weight: 650;
    text-decoration: none;
}

.btn:hover {
    filter: brightness(1.06);
}

.btn-secondary {
    background: transparent;
    color: var(--ink);
    border: 1px solid var(--line);
}

/* Official App Store badge (Apple's artwork, not restyled). */
.badge-appstore {
    display: inline-flex;
}

.badge-appstore img {
    height: 52px;
    width: auto;
    display: block;
}

/* ---------- Sections ---------- */
.section {
    padding-block: var(--s-8);
}

.section-tight {
    padding-block: var(--s-7);
}

.section-alt {
    background: var(--bg-raised);
}

.kicker {
    font-family: var(--font-display);
    font-size: 0.85rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--accent-text);
    margin: 0 0 var(--s-2);
}

.lede {
    font-size: 1.15rem;
    color: var(--ink-muted);
}

/* ---------- Hero ----------
   Light, like everything else (ADR-H3 amendment 2026-09-04). A soft wash from white to
   the icon's gradient midtone (--hero-tint), so the hero belongs to the same page as the
   light screenshots below it. Text uses the page tokens: ink 13.52:1 and muted 4.71:1 on
   the tint (measured at the darkest point of the gradient). */
.hero {
    padding-block: var(--s-9) var(--s-8);
    text-align: center;
    color: var(--ink);
    background-color: var(--bg);
    background-image:
        radial-gradient(60% 55% at 50% 0%, rgba(151, 196, 245, 0.28), transparent 70%),
        linear-gradient(#FFFFFF, var(--hero-tint));
}

.hero .lede {
    color: var(--ink-muted);
}

.hero .cta-note {
    color: var(--ink-muted);
}

.hero .measure {
    margin-inline: auto;
}

.app-icon {
    border-radius: 22%;
    margin-bottom: var(--s-5);
}

.cta-row {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: var(--s-4);
    margin-top: var(--s-5);
}

.cta-note {
    margin-top: var(--s-4);
    font-size: 0.95rem;
    color: var(--ink-muted);
}

/* ---------- Feature grid ---------- */
.grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
    gap: var(--s-5);
    margin-top: var(--s-6);
}

/* Cards alternate between the two real surfaces so they always lift or recede
   against the section behind them, and so a link inside a card always lands on a
   surface where --accent-text clears AA (6.75:1 on raised, 8.56:1 on bg — dark;
   6.15:1 / 5.77:1 — light). There is no third surface token on purpose. */
.card {
    background: var(--bg-raised);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: var(--s-5);
}

.section-alt .card {
    background: var(--bg);
}

.card p:last-child {
    margin-bottom: 0;
}

.card .glyph {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 12px;
    background: var(--hl-blue);
    color: var(--on-blue);
    margin-bottom: var(--s-4);
}

.chart-list {
    margin: var(--s-3) 0 0;
    padding-left: var(--s-5);
    color: var(--ink-muted);
}

/* ---------- Privacy USP ---------- */
.usp {
    background: var(--bg-raised);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    padding: var(--s-6);
}

.usp-points {
    margin: var(--s-4) 0 0;
    padding-left: var(--s-5);
    color: var(--ink-muted);
}

.usp-points li + li {
    margin-top: var(--s-2);
}

/* ---------- Screenshots ---------- */
.shots {
    display: flex;
    align-items: flex-end;
    gap: var(--s-5);
    margin-top: var(--s-6);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    margin-inline: calc(var(--s-5) * -1);   /* edge-bleed so the row can scroll past the gutter */
    padding-inline: var(--s-5);
    padding-bottom: var(--s-4);
}

.shot {
    flex: 0 0 auto;
    margin: 0;
    scroll-snap-align: center;
}

.shot:first-child {
    margin-inline-start: auto;
}

.shot:last-child {
    margin-inline-end: auto;
}

.shots img {
    height: 360px;
    width: auto;
    border: 1px solid var(--line);
    border-radius: 14px;
    display: block;
}

.shot.wide img {
    height: 210px;
}

.shot-caption {
    margin-top: var(--s-3);
    text-align: center;
    font-size: 0.9rem;
    color: var(--ink-muted);
}

/* ---------- Screenshot placeholders (TEMPORARY — must never reach production) ----------
   Deliberately unmistakable: a hazard-striped, dashed, blue-bordered box labelled with
   its shot number and target filename. It must be impossible to sign off by accident.

   Aspect ratio comes from the REAL device screen (--ar, set inline per shot) so the
   layout does not reflow when the captures land.

   There are deliberately NO width/height attributes anywhere here: a placeholder
   dimension must never be carried into production. At swap-in the whole
   .shot-placeholder element is replaced by the <a class="shot-link"><picture> block,
   and its width/height are MEASURED from the produced files (ADR-H4).

   scripts/deploy.sh refuses a cutover while any page still references one. */
.shot-placeholder {
    height: 360px;
    aspect-ratio: var(--ar);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--s-2);
    padding: var(--s-4);
    text-align: center;
    border: 3px dashed var(--hl-blue);
    border-radius: 14px;
    color: var(--ink);
    background-color: var(--bg-raised);
    background-image: repeating-linear-gradient(45deg,
            transparent 0 14px,
            rgba(151, 196, 245, 0.16) 14px 28px);
}

.shot-placeholder .ph-num {
    font-family: var(--font-display);
    font-size: 1.6rem;
    font-weight: 800;
    line-height: 1;
    color: var(--accent-text);
}

.shot-placeholder .ph-label {
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--accent-text);
}

.shot-placeholder .ph-file {
    font-family: var(--font-mono);
    font-size: 0.66rem;
    line-height: 1.35;
    color: var(--ink-muted);
    word-break: break-word;
    max-width: 22ch;
}

.shot.wide .shot-placeholder {
    height: 210px;
}

/* ---------- Platforms ---------- */
.platform-note {
    margin-top: var(--s-5);
    font-size: 0.95rem;
    color: var(--ink-muted);
}

/* ---------- Pricing ---------- */
.pricing-lead {
    max-width: none;   /* full container width, as the legal pages */
}

.pricing-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: var(--s-5);
    margin-top: var(--s-6);
}

.plan-name {
    font-family: var(--font-display);
    font-weight: 700;
    margin: 0 0 var(--s-2);
}

.price-line {
    font-family: var(--font-display);
    font-size: 1.9rem;
    font-weight: 800;
    margin: 0 0 var(--s-1);
}

.plan-note {
    font-size: 0.95rem;
    color: var(--ink-muted);
    margin: 0;
}

.card.featured {
    border-color: var(--hl-blue);
}

.plan-badge {
    display: inline-block;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    padding: 3px 9px;
    border-radius: 999px;
    background: var(--hl-blue);
    color: var(--on-blue);
    margin-bottom: var(--s-3);
}

/* Unconfirmed-price marker (TEMPORARY — must never reach production).
   No figure appears anywhere until Patrick has confirmed the CHF amounts in App Store
   Connect (2026-09-04). The marker is styled like the screenshot placeholders so it
   cannot be mistaken for a price, and scripts/deploy.sh refuses a cutover while any
   page carries it. */
.price-pending {
    display: inline-block;
    font-family: var(--font-mono);
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    padding: 4px 10px;
    border: 2px dashed var(--hl-blue);
    border-radius: 8px;
    color: var(--accent-text);
    background-image: repeating-linear-gradient(45deg,
            transparent 0 8px,
            rgba(151, 196, 245, 0.16) 8px 16px);
}

/* Regional-price qualifier. Required on the section that names a figure — these are
   Swiss App Store tiers and read as worldwide prices without it. */
.pricing-note {
    margin-top: var(--s-5);
    font-size: 0.95rem;
    color: var(--ink-muted);
}

/* ---------- FAQ ---------- */
.faq details {
    border-bottom: 1px solid var(--line);
    padding-block: var(--s-4);
}

.faq summary {
    font-family: var(--font-display);
    font-weight: 700;
    cursor: pointer;
    min-height: 44px;
    display: flex;
    align-items: center;
}

.faq details p {
    margin-top: var(--s-3);
    margin-bottom: 0;
    color: var(--ink-muted);
}

/* ---------- Legal pages ----------
   Body prose at the full container width, no .measure — the same width as the footer
   paragraph and the landing page's section notes (PladioWeb's 2026-09-03 decision,
   inherited for consistency across the KREANIQS sites). */
.legal {
    padding-block: var(--s-7);
}

.doc-meta {
    color: var(--ink-muted);
    font-size: 0.95rem;
}

/* Draft banner. Removed once the page's content is final — see the launch checklist. */
.draft-notice {
    border: 1px solid var(--hl-blue);
    border-radius: var(--radius);
    padding: var(--s-4);
    margin-bottom: var(--s-6);
    background: var(--bg-raised);
}

.legal h2 {
    margin-top: var(--s-6);
    font-size: 1.4rem;
}

.legal h3 {
    margin-top: var(--s-5);
    font-size: 1.1rem;
}

.legal ul,
.legal ol {
    padding-left: var(--s-5);
}

.legal li + li {
    margin-top: var(--s-2);
}

.legal table {
    border-collapse: collapse;
    width: 100%;
    margin: var(--s-4) 0;
    font-size: 0.95rem;
}

.legal th,
.legal td {
    text-align: left;
    vertical-align: top;
    padding: var(--s-2) var(--s-3);
    border-bottom: 1px solid var(--line);
}

.legal .table-scroll {
    overflow-x: auto;
}

/* Website-only addendum on a mirrored legal page (ADR-H7): visibly scoped, so nobody
   reads it as part of the in-app document. */
.addendum {
    border: 1px solid var(--line);
    border-left: 4px solid var(--hl-blue);
    border-radius: 0 var(--radius) var(--radius) 0;
    padding: var(--s-4) var(--s-5);
    margin-top: var(--s-6);
    background: var(--bg-raised);
}

/* ---------- Verification flags in legal drafts (TEMPORARY) ----------
   Marks a statement that could NOT be verified in the app source, or that contradicts
   it, so Patrick can scan for them during review. Removed at cutover; unresolved ones
   move to a HOG ticket. */
.flag {
    display: block;
    margin: var(--s-4) 0;
    padding: var(--s-3) var(--s-4);
    border-left: 4px solid var(--hl-blue);
    border-radius: 0 var(--radius) var(--radius) 0;
    background: var(--bg-raised);
    font-size: 0.95rem;
}

.section-alt .flag {
    background: var(--bg);
}

.flag::before {
    content: "UNVERIFIED";
    display: block;
    font-family: var(--font-mono);
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    color: var(--accent-text);
    margin-bottom: var(--s-1);
}

.flag.contradiction::before {
    content: "CONTRADICTS THE SOURCE";
}

/* A fact confirmed by Patrick from a system this repo cannot read. Distinct from .flag:
   that one means "nobody can verify this", this one means "verified, just not from the
   source tree". Muted rather than blue, because it needs recording and not chasing. */
.flag.verified {
    border-left-color: var(--ink-muted);
}

.flag.verified::before {
    content: "VERIFIED OUT-OF-BAND";
    color: var(--ink-muted);
}

/* The recording-pending marker on /privacy/ "This website": same muted look as
   .flag.verified, but its own class on purpose — it is a RE-SCOPED gate (deploy.sh
   check_recording_flag): reported on staging and on the cutover deploy, refused on the
   first routine deploy after cutover until recording 3 on production agrees. Never give
   it the "flag" class (that gate refuses at cutover) and never remove the class without
   the recording. */
.recording-pending {
    display: block;
    margin: var(--s-4) 0;
    padding: var(--s-3) var(--s-4);
    border-left: 4px solid var(--ink-muted);
    border-radius: 0 var(--radius) var(--radius) 0;
    background: var(--bg-raised);
    font-size: 0.95rem;
}

.recording-pending::before {
    content: "MEASURED ON LOCALHOST AND STAGING — PRODUCTION PENDING";
    display: block;
    font-family: var(--font-mono);
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    color: var(--ink-muted);
    margin-bottom: var(--s-1);
}

/* ---------- Footer ---------- */
.site-footer {
    border-top: 1px solid var(--line);
    padding-block: var(--s-6);
    font-size: 0.95rem;
    color: var(--ink-muted);
}

.site-footer nav {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-4);
    margin-bottom: var(--s-4);
}

/* Footer links are a wrapped flex row, not inline prose, so the inline-text exemption
   does not apply: each is a 44px target. The row simply grows. */
.site-footer nav a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
}

.site-footer p {
    margin-bottom: var(--s-2);
}

.attribution {
    margin-bottom: 0;
}

/* Credits: the six open-source notices from Settings → Attribution, verbatim. Folded
   behind a <details> so the footer stays short; the <summary> is a 44px target. */
.credits summary {
    cursor: pointer;
    display: flex;
    align-items: center;
    min-height: 44px;
    font-weight: 600;
}

.credits ul {
    margin: var(--s-2) 0 0;
    padding-left: var(--s-5);
}

.credits li + li {
    margin-top: var(--s-1);
}

/* ---------- Lightbox ---------- */
.lb-open {
    overflow: hidden;
}

.lightbox {
    border: 0;
    padding: 0;
    background: transparent;
    max-width: 92vw;
    max-height: 92vh;
}

.lightbox::backdrop {
    background: rgba(0, 0, 0, 0.8);
}

.lightbox img {
    display: block;
    max-height: 86vh;
    max-height: 86dvh;
    width: auto;
    border-radius: var(--radius);
}

.lb-close {
    position: absolute;
    top: var(--s-2);
    right: var(--s-2);
    width: 44px;
    height: 44px;
    border: 0;
    border-radius: 999px;
    background: var(--bg-raised);
    color: var(--ink);
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
}

/* ---------- Feedback portal (Upvoty) — wired in Phase 5 ---------- */
.portal-frame {
    margin-top: var(--s-6);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    overflow: hidden;
}

.portal-frame iframe {
    display: block;
    width: 100%;
    border: 0;
    height: 75vh;
    height: clamp(28rem, 80dvh, 56rem);
}

.portal-fallback {
    margin-top: var(--s-4);
    font-size: 0.95rem;
    color: var(--ink-muted);
}

/* ---------- Responsive ----------
   Only two width breakpoints, and both exist solely to grow the screenshot row.
   Everything else is intrinsically responsive: clamp() type, auto-fit grids, and the
   --measure / --page-max caps. */
@media (min-width: 768px) {
    .shots img,
    .shot-placeholder {
        height: 420px;
    }

    .shot.wide img,
    .shot.wide .shot-placeholder {
        height: 250px;
    }
}

@media (min-width: 1024px) {
    .shots img,
    .shot-placeholder {
        height: 440px;
    }

    .shot.wide img,
    .shot.wide .shot-placeholder {
        height: 265px;
    }
}
