/* Pladio — design foundation (dark-mode-first)
   Palette derived from the app's Source/Assets.xcassets, not invented (ADR-P3).

   Tokens validated for WCAG AA — these ratios are measured, and they are the
   reason several tokens exist at all. Re-validate when touching any of them:
     accent-text on bg          5.79:1  ·  accent-text on bg-raised   5.06:1
     accent-text light on bg    5.13:1  ·  ink on bg (dark)          15.93:1
     ink-muted on bg (dark)     7.24:1  ·  ink-muted on bg (light)    4.86:1
     on-orange ink on orange    5.02:1

   Three traps, each already sprung once:
   1. WHITE ON THE BRAND ORANGE IS 3.39:1 AND FAILS AA. Buttons use --on-orange
      (the app's own dark surface) at 5.02:1. Never white.
   2. --pl-orange (#EC5E1E) is 4.39:1 on --bg-raised, under AA for body text.
      It is a FILL, not a text colour. Text uses --accent-text.
   3. In light mode the brand orange drops to 3.17:1 on --bg. --accent-text is
      darkened to #B84210 there. Never use --pl-orange for text on light. */
:root {
    /* Brand */
    --pl-orange: #EC5E1E;

    /* AccentColor.colorset — fills, buttons, decorative. NEVER text. */
    --accent-text: #F0713A;

    /* link/kicker text on dark surfaces — the smallest shift off the brand
       orange that clears AA on both --bg and --bg-raised */
    --on-orange: #1A1A2E;

    /* text on orange surfaces (buttons) */
    /* Neutrals (dark — default), from the app's asset catalog */
    --bg: #1A1A2E;

    /* BackgroundColor.colorset, dark */
    --bg-raised: #25253C;

    /* CardColor.colorset, dark */
    --bg-inset: #2F2F4A;

    /* derived, NOT from the asset catalog. Muted text only (5.48:1) — links
       fail here at 4.38:1, so nothing that can contain one may use it. */
    --ink: #F7F7F8;

    /* TextPrimaryColor.colorset, dark */
    --ink-muted: #A8A8B3;

    /* TextSecondaryColor.colorset, dark */
    --line: rgba(247, 247, 248, 0.14);

    /* Type — rounded display via ui-rounded (renders SF Pro Rounded on Apple
       devices). Zero font bytes; the self-only 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;

    /* 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;
    color-scheme: dark light;
}

@media (prefers-color-scheme: light) {
    :root {
        --accent-text: #B84210;

        /* the brand orange is 3.17:1 here — too low for text */
        --bg: #F7F7F8;
        --bg-raised: #FFFFFF;
        --bg-inset: #EFEFF2;
        --ink: #1A1A2E;
        --ink-muted: #6B6B80;
        --line: rgba(26, 26, 46, 0.12);
    }
}

/* ---------- 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;
}

/* 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, so legal copy keeps its density
   and the pages do not get longer.
   The values are the largest that fit inside the existing half-leading, so hit
   boxes on adjacent wrapped lines stay apart. Do NOT raise these toward 44px:
   the boxes would overlap, the upper link would win hit-testing, and the lower
   one would get harder to hit. */
.legal p a,
.faq details p a {
    /* 20px content in a 27px line box -> 24px */
    padding-block: 2px;
}

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

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;

    /* Keyboard-only, but a target is a target: 44px (WCAG 2.5.8). */
    display: inline-flex;
    align-items: center;
    min-height: 44px;
}

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

/* ---------- Justified prose (all pages, decided 2026-09-03) ----------
   Body copy is justified site-wide; hyphens: auto keeps rivers down (every page
   declares lang="en"). The hero stays centred -- it is a centred composition, and a
   justified two-line lede under a centred heading reads as a mistake. */
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;

    /* 44px target. Layout-neutral: the header's .btn beside it is already 48px. */
    min-height: 44px;
}

.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(--pl-orange);
    color: var(--on-orange);

    /* 5.02:1. White here is 3.39:1 and fails AA — see the header comment. */
    font-weight: 650;
    text-decoration: none;
}

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

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

.badge-appstore {
    display: inline-block;
}

.badge-appstore img {
    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 ---------- */
.hero {
    padding-block: var(--s-9) var(--s-8);
    text-align: center;

    /* Background: the iPad mockup from PladioAssets/Mockups (1920x1440 master, derived
       with sips --resampleWidth for the 1280 variant, WebP + JPEG, ADR-P4), under a
       dark scrim. The scrim is what carries the contrast: text sits on ~#1A1A2E at
       ~80% over the photo, so the hero stays dark in BOTH colour schemes on purpose --
       the light-scheme tokens are not applied inside it. */
    color: #F7F7F8;
    background-color: #1A1A2E;
    background-image: linear-gradient(rgba(26, 26, 46, 0.78), rgba(26, 26, 46, 0.86)),
        url("/img/hero-ipad-1280.jpg?v=1");
    background-size: cover;
    background-position: center;
}

.hero .lede {
    color: #D6D6DE;
}

.hero .cta-note {
    color: #C4C4CE;
}

@supports (background-image: image-set(url("a.webp") type("image/webp"))) {
    .hero {
        background-image: linear-gradient(rgba(26, 26, 46, 0.78), rgba(26, 26, 46, 0.86)),
            image-set(url("/img/hero-ipad-1280.webp?v=1") type("image/webp"),
                      url("/img/hero-ipad-1280.jpg?v=1") type("image/jpeg"));
    }
}

@media (min-width: 1024px) {
    .hero {
        background-image: linear-gradient(rgba(26, 26, 46, 0.78), rgba(26, 26, 46, 0.86)),
            url("/img/hero-ipad-1920.jpg?v=1");
    }

    @supports (background-image: image-set(url("a.webp") type("image/webp"))) {
        .hero {
            background-image: linear-gradient(rgba(26, 26, 46, 0.78), rgba(26, 26, 46, 0.86)),
                image-set(url("/img/hero-ipad-1920.webp?v=1") type("image/webp"),
                          url("/img/hero-ipad-1920.jpg?v=1") type("image/jpeg"));
        }
    }
}

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

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

.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 app's 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:
     card on a default section -> --bg-raised   (accent 5.06:1)
     card on a .section-alt    -> --bg          (accent 5.79:1)
   Do not put a card on --bg-inset: accent is 4.38:1 there and fails. */
.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;
    text-align: justify;
}

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

/* ---------- 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;

    /* edge-bleed so the row can scroll past the page gutter */
    margin-inline: calc(var(--s-5) * -1);
    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, orange-bordered box labelled with
   its shot number and target filename. It must be impossible to sign off by accident,
   which is why it is not a plausible grey rectangle.

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

   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 with
   `sips -g pixelWidth -g pixelHeight` (ADR-P4) — never inherited from this file.

   scripts/deploy.sh refuses to deploy 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(--pl-orange);
    border-radius: 14px;
    color: var(--ink);
    background-color: var(--bg-raised);
    background-image: repeating-linear-gradient(45deg,
            transparent 0 14px,
            rgba(236, 94, 30, 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: ui-monospace, SFMono-Regular, Menlo, monospace;
    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);
}

/* ---------- Roadmap callout ---------- */
.roadmap-note {
    border: 1px dashed var(--line);
    border-radius: var(--radius);
    padding: var(--s-5);
    margin-top: var(--s-6);
}

.tag {
    display: inline-block;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    padding: 4px 10px;
    border-radius: 999px;
    background: var(--bg-inset);
    color: var(--ink-muted);
    margin-bottom: var(--s-3);
}

/* ---------- Pricing ---------- */
.pricing-lead {
    /* Full container width by decision (2026-09-03) -- same as the legal pages. */
    max-width: none;
}

.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(--pl-orange);
}

.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(--pl-orange);
    color: var(--on-orange);
    margin-bottom: var(--s-3);
}

/* Regional-price qualifier. Required on every page 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 ---------- */
.legal {
    padding-block: var(--s-7);
}

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

/* Draft banner for legal documents awaiting review. Removed at cutover —
   see the launch checklist in CLAUDE.md. */
.draft-notice {
    border: 1px solid var(--pl-orange);
    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 {
    padding-left: var(--s-5);
}

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

/* ---------- Verification flags in legal drafts (TEMPORARY) ----------
   Marks a statement that could NOT be verified in the app source, so Patrick can
   scan for them during review instead of reading for them. Removed, together with
   .draft-notice, once each flag is resolved. */
.flag {
    display: block;
    margin: var(--s-4) 0;
    padding: var(--s-3) var(--s-4);
    border-left: 4px solid var(--pl-orange);
    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: ui-monospace, SFMono-Regular, Menlo, monospace;
    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 I cannot read (a vendor dashboard,
   a mail admin console). Distinct from .flag: that one means "nobody can verify
   this", this one means "verified, just not from the source tree". Muted rather
   than orange, 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);
}

/* ---------- 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;
   no negative margin, which would overlap the wrapped rows' hit-boxes. */
.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;
}

/* ---------- 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) ---------- */
.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;
    }
}
