:root {
    /* A primed canvas, the same off-white as the board in the app's lid. */
    --ground: #efede7;
    --ground-deep: #e2dfd6;
    /* Text is the app's ivory black. */
    --ink: #2a292d;
    --ink-soft: #57555a;
    --ink-faint: #85827f;
    --accent: #1c29ab; /* ultramarine */
    --rule: rgba(42, 41, 45, 0.14);

    --font-serif: "Source Serif 4", "Iowan Old Style", Georgia, serif;
    --font-body: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial, sans-serif;

    color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
    :root {
        /* A canvas toned with ivory black, like painting on black gesso. */
        --ground: #2b2a2e;
        --ground-deep: #1e1d20;
        --ink: #f3f1ec;
        --ink-soft: #b8b5b0;
        --ink-faint: #85827e;
        --accent: #ffcb00; /* cadmium yellow */
        --rule: rgba(243, 241, 236, 0.14);
    }
}

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

html,
body {
    height: 100%;
}

body {
    background: var(--ground);
    color: var(--ink);
    font-family: var(--font-body);
    -webkit-font-smoothing: antialiased;
}

a {
    color: inherit;
}

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

/* ---------- Single-screen home page ---------- */

.home {
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
    display: grid;
    grid-template-rows: 1fr auto;
    /* The photo's own sky and grass, sampled at its top and bottom edges. */
    --sky: #4b7ebc;
    --grass: #344219;
    --edge: 10px; /* the strips for Safari, below; it ignored a 2px strip */
    /* The lake photo, blurred ahead of time so the words stand out. Its top and bottom
       fade into the sky and grass colors, the same colors Safari is given for its bars below. */
    background:
        linear-gradient(var(--sky) var(--edge), transparent 3.5rem),
        linear-gradient(to top, var(--grass) var(--edge), transparent 3.5rem),
        url("images/realistic_lake_blurred.jpg") center / cover no-repeat var(--sky);
    /* White text reads over the blurred photo in light and dark mode alike. */
    --ink: #fff;
    --ink-soft: rgba(255, 255, 255, 0.9);
    --ink-faint: rgba(255, 255, 255, 0.75);
    color: var(--ink);
}

/* Safari on iPhone fills the space behind its status bar and toolbar with one flat color
   each. It takes them from solid fixed elements touching the top and bottom of the page
   (otherwise both get the page color), so these strips hand it the sky for the top and the
   grass for the bottom, and the photo seems to carry on under the bars. Safari passes over
   pseudo-elements here, so the strips are elements in index.html. */
.edge {
    position: fixed;
    left: 0;
    right: 0;
    height: var(--edge);
}

.edge-top {
    top: 0;
    background: var(--sky);
}

.edge-bottom {
    bottom: 0;
    background: var(--grass);
}

.home .intro,
.home .site-footer {
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35), 0 2px 12px rgba(0, 0, 0, 0.3);
}

.home > .stage,
.home > .site-footer {
    position: relative;
}

.stage {
    display: grid;
    grid-template-columns: minmax(300px, 0.75fr) 1.25fr;
    align-items: center;
    gap: 2rem;
    padding: 2rem clamp(1.5rem, 5vw, 5rem) 0;
    padding-left: max(clamp(1.5rem, 5vw, 5rem), env(safe-area-inset-left));
    padding-right: max(clamp(1.5rem, 5vw, 5rem), env(safe-area-inset-right));
    min-height: 0;
}

.intro {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    max-width: 31rem;
}

picture {
    display: contents;
}

.app-icon {
    width: 72px;
    height: 72px;
    border-radius: 22.5%;
    /* Layered so it reads as a small object resting just above the canvas. */
    box-shadow:
        0 1px 1px rgba(30, 24, 18, 0.14),
        0 3px 6px rgba(30, 24, 18, 0.16),
        0 10px 20px rgba(30, 24, 18, 0.18),
        0 24px 44px rgba(30, 24, 18, 0.22);
    margin-bottom: 1.75rem;
}

/* ---------- Name and copy ---------- */

.app-name {
    font-family: var(--font-serif);
    font-optical-sizing: auto;
    font-weight: 900;
    font-size: clamp(3rem, 6.2vw, 5.4rem);
    line-height: 1;
    letter-spacing: -0.015em;
    margin-bottom: 1.1rem;
}

.description {
    font-family: var(--font-serif);
    font-size: clamp(1.1rem, 1.45vw, 1.3rem);
    line-height: 1.55;
    color: var(--ink-soft);
    margin-bottom: 2rem;
    text-wrap: pretty;
}

/* Follows the description as a quieter second paragraph. */
.description:has(+ .no-undo) {
    margin-bottom: 0.9rem;
}

.no-undo {
    font-style: italic;
    color: var(--ink-faint);
}

.app-store-badge {
    display: inline-block;
    line-height: 0;
    transition: transform 0.2s ease;
}

.app-store-badge:hover {
    transform: translateY(-1px) rotate(-1deg);
}

.app-store-badge img {
    height: 54px;
    width: auto;
}

.compat {
    display: flex;
    align-items: center;
    gap: 0.45em;
    margin-top: 1rem;
    font-family: var(--font-serif);
    font-size: 0.95rem;
    color: var(--ink-soft);
}

.pencil {
    flex: none;
    width: 1.6em;
    height: 1.6em;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.4;
    stroke-linejoin: round;
    stroke-linecap: round;
}

/* ---------- The rendered iPhone Duo ---------- */

.scene {
    /* --w is the device width; every other device measurement derives from it. */
    --w: min(44vw, 56vh, 760px);
    --t: calc(var(--w) * 0.028); /* thickness of each half */
    --b: calc(var(--w) * 0.018); /* bezel */
    /* The screen's corners follow the app's tin, about 82px across a 1004px-wide frame;
       the outer corners stay concentric with them, one bezel out. */
    --sr: calc((var(--w) - var(--b) * 2) * 0.0817); /* screen corner radius */
    --r: calc(var(--sr) + var(--b)); /* outer corner radius */
    --open: -74deg; /* lid angle; -90deg is upright, -180deg is closed */
    --crease: calc(var(--w) * 0.06); /* length of screen that bends through the fold */
    /* Height over width of the screen image (1112 x 1613). Each half is sized so the
       unfolded screen (lid + crease + base, inside the bezel) has exactly this shape. */
    --media-aspect: 1.42231;
    --h: calc(((var(--w) - var(--b) * 2) * var(--media-aspect) - var(--crease)) / 2 + var(--b));

    position: relative;
    height: 100%;
    min-height: 0;
}

.view {
    height: 100%;
    display: grid;
    place-items: center;
    perspective: calc(var(--w) * 4.2);
    perspective-origin: 50% 20%;
}

.duo {
    position: relative;
    width: var(--w);
    height: var(--h);
    transform-style: preserve-3d;
    /* The script turns this toward the pointer. */
    transform: translateY(calc(var(--h) * 0.36)) rotateX(56deg) rotateZ(-20deg);
}

.half,
.bend {
    position: absolute;
    left: 0;
    width: 100%;
    transform-style: preserve-3d;
}

.half {
    height: var(--h);
}

.base {
    top: 0;
}

/* The screen bends through the crease in short strips, each turned a little, so it
   curves from the base into the lid. The lid hangs off the last strip. */
.bend {
    bottom: 100%;
    height: calc(var(--crease) / 8);
    transform-origin: 50% 100%;
    transform: rotateX(calc(var(--open) / 8));
}

.base > .bend,
.lid {
    transform-origin: 50% 100%;
    transform: rotateX(calc(var(--open) / 16));
}

.lid {
    bottom: 100%;
}

/* Animating --open (registered below) swings the lid and the crease together. */
@property --open {
    syntax: "<angle>";
    inherits: true;
    initial-value: -74deg;
}

.duo {
    animation: open-lid 1.6s cubic-bezier(0.3, 0.6, 0.2, 1) 0.2s both;
}

@keyframes open-lid {
    from { --open: -179deg; }
}

.face {
    position: absolute;
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
}

.front {
    inset: 0;
    background: #08080a;
}

.lid > .front { border-radius: var(--r) var(--r) 0 0; }
.base > .front { border-radius: 0 0 var(--r) var(--r); }

.back {
    inset: 0;
    transform: translateZ(calc(var(--t) * -1)) rotateY(180deg);
    background: linear-gradient(160deg, #5a5856, #3c3b3a 60%, #2e2d2c);
}

.lid > .back { border-radius: var(--r) var(--r) 0 0; }
.base > .back { border-radius: 0 0 var(--r) var(--r); }

/* The frame: rounded slices stacked through the thickness, so the edge follows the corners.
   Each slice is lit from the upper left, so edges facing that way read lighter. */
.layer {
    inset: 0;
    /* Solid from both sides: from outside the crease, the slices are the device's spine. */
    backface-visibility: visible;
    -webkit-backface-visibility: visible;
    background: linear-gradient(200deg, #b4b1ad 0%, #85827e 35%, #4b4946 75%, #3a3836 100%);
}

.lid > .layer { border-radius: var(--r) var(--r) 0 0; }
.base > .layer { border-radius: 0 0 var(--r) var(--r); }

/* Crease strips are too short for the diagonal light, so shade them side to side only. */
.bend > .layer {
    background: linear-gradient(to right, #9c9995, #6f6c68 45%, #42403d);
}

/* The screen. Each part's canvas is its own face in the 3D scene, a sibling of the bezel
   rather than nested in it: Safari only hides the back of faces that take part in the scene
   directly, so a nested canvas showed through the lid's back as it folded. */
.screen-canvas {
    left: var(--b);
    width: calc(100% - var(--b) * 2);
    transform: translateZ(0.5px);
    background: #000;
}

.lid > .screen-canvas {
    top: var(--b);
    height: calc(100% - var(--b));
    border-radius: var(--sr) var(--sr) 0 0;
}

.base > .screen-canvas {
    top: 0;
    height: calc(100% - var(--b));
    border-radius: 0 0 var(--sr) var(--sr);
}

/* Strips overlap their neighbors by a pixel so no hairline seams show between them. */
.bend > .front {
    inset: -1px 0;
}

.bend > .screen-canvas {
    top: -1px;
    height: calc(100% + 2px);
}

/* Reflections, floating just above the glass. The crease strips carry none, so each
   reflection fades out before the fold rather than stopping hard at its edge. */
.glare {
    transform: translateZ(1px);
    pointer-events: none;
}

.lid > .glare {
    inset: var(--b) var(--b) 0 var(--b);
    border-radius: var(--sr) var(--sr) 0 0;
    background: linear-gradient(115deg, rgba(255, 255, 255, 0.10) 0%, rgba(255, 255, 255, 0.02) 38%, transparent 38.2%);
    -webkit-mask-image: linear-gradient(to top, transparent, #000 35%);
    mask-image: linear-gradient(to top, transparent, #000 35%);
}

.base > .glare {
    inset: 0 var(--b) var(--b) var(--b);
    border-radius: 0 0 var(--sr) var(--sr);
    background: linear-gradient(200deg, rgba(255, 255, 255, 0.06), transparent 45%);
    -webkit-mask-image: linear-gradient(to bottom, transparent, #000 35%);
    mask-image: linear-gradient(to bottom, transparent, #000 35%);
}

.table-shadow,
.contact-shadow,
.lid-shadow {
    position: absolute;
    pointer-events: none;
}

/* The soft pool of shade on the table around the device. The device covers the middle
   of the ellipse, so the shade has to hold its strength out to the device's edges
   (about three quarters of the way out) before it fades. It reaches back past the hinge,
   where the open lid keeps light off the table. */
.table-shadow {
    inset: -30% -16% -20% -16%;
    transform: translateZ(calc(var(--t) * -1 - 2px));
    background: radial-gradient(ellipse 50% 50% at 50% 46%,
        rgba(30, 24, 18, 0.5) 0%, rgba(30, 24, 18, 0.42) 66%, rgba(30, 24, 18, 0.16) 86%, transparent 100%);
    filter: blur(calc(var(--w) * 0.035));
}

/* Where the base meets the table: tight and dark, so the device sits on the canvas. */
.contact-shadow {
    inset: -1% -1.2% -2.5% -1.2%;
    transform: translateZ(calc(var(--t) * -1 - 1px));
    border-radius: 0 0 var(--r) var(--r);
    background: rgba(24, 19, 14, 0.5);
    filter: blur(calc(var(--w) * 0.01));
}

/* The lid's shadow, thrown back across the table by light from the front. It runs longer
   than the lid is tall, so it shows past the lid's top edge and lifts it off the page. */
.lid-shadow {
    left: -3%;
    right: -3%;
    bottom: 100%;
    height: 150%;
    transform: translateZ(calc(var(--t) * -1 - 1.5px));
    background: linear-gradient(to top, rgba(30, 24, 18, 0.5), rgba(30, 24, 18, 0.26) 50%, transparent);
    border-radius: 40% 40% 0 0 / 20% 20% 0 0;
    filter: blur(calc(var(--w) * 0.04));
}

/* ---------- Footer ---------- */

.site-footer {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem 1.5rem;
    padding: 1rem clamp(1.5rem, 5vw, 5rem) 1.25rem;
    padding-left: max(clamp(1.5rem, 5vw, 5rem), env(safe-area-inset-left));
    padding-right: max(clamp(1.5rem, 5vw, 5rem), env(safe-area-inset-right));
    padding-bottom: max(1.25rem, env(safe-area-inset-bottom));
    font-size: 0.8125rem;
    color: var(--ink-faint);
}

.footer-links {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1.5rem;
}

.site-footer a {
    text-decoration: none;
    color: var(--ink-soft);
}

.site-footer a:hover {
    color: var(--ink);
}

/* ---------- Narrow and portrait screens ---------- */

@media (max-width: 820px), (max-aspect-ratio: 1/1) {
    /* The page is one screen tall, and only grows (and scrolls) when the copy leaves too
       little room under it for the device. svh rather than dvh, so the page doesn't resize
       as Safari's toolbar shrinks and grows. */
    .home {
        height: auto;
        min-height: 100vh;
        min-height: 100svh;
        overflow: visible;
    }

    .stage {
        grid-template-columns: 1fr;
        grid-template-rows: auto minmax(16rem, 1fr);
        align-items: start;
        gap: 0;
        padding-top: clamp(1.25rem, 4vh, 3rem);
        text-align: center;
    }

    .intro {
        align-items: center;
        margin: 0 auto;
    }

    .app-icon {
        width: 56px;
        height: 56px;
        margin-bottom: 1rem;
    }

    .app-name {
        font-size: clamp(2.5rem, 11vw, 3.75rem);
        margin-bottom: 0.6rem;
    }

    .description {
        font-size: 1.05rem;
        margin-bottom: 1.25rem;
    }

    .app-store-badge img {
        height: 46px;
    }

    .compat {
        margin-top: 0.75rem;
        font-size: 0.9rem;
    }

    /* The device fills whatever room is left under the copy. Seen in perspective it stands
       about 1.35 times as tall as --w and 1.3 times as wide, so these keep all of it inside
       the scene instead of rising over the badge. */
    .scene {
        container-type: size;
        padding-top: 1rem;
        --w: min(66cqw, 70cqh, 520px);
    }

    .site-footer {
        justify-content: center;
        text-align: center;
    }
}

/* Small phones: the copy tightens to keep the device on screen. */
@media (max-width: 420px) {
    .description {
        font-size: 0.98rem;
        line-height: 1.45;
    }
}

@media (max-height: 560px) and (min-width: 821px) {
    .app-icon { display: none; }
}

@media (prefers-color-scheme: dark) {
    /* A dark table shadow disappears on a dark page, so let the screen light the table instead,
       and keep the shadows that are left near black. */
    .table-shadow {
        background:
            radial-gradient(ellipse 50% 50% at 50% 46%,
                rgba(255, 214, 120, 0.2) 0%, rgba(255, 214, 120, 0.16) 66%, rgba(90, 140, 255, 0.07) 86%, transparent 100%);
    }

    .contact-shadow {
        background: rgba(0, 0, 0, 0.75);
    }

    .lid-shadow {
        background: linear-gradient(to top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.26) 55%, transparent);
    }

    .app-icon {
        box-shadow:
            0 0 0 1px rgba(255, 255, 255, 0.06),
            0 1px 1px rgba(0, 0, 0, 0.3),
            0 3px 6px rgba(0, 0, 0, 0.32),
            0 10px 20px rgba(0, 0, 0, 0.36),
            0 24px 44px rgba(0, 0, 0, 0.42);
    }
}

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

/* ---------- Text pages (privacy, support) ---------- */

.page-body {
    background: var(--ground);
    min-height: 100%;
}

.page {
    max-width: 40rem;
    margin: 0 auto;
    padding: 3rem 1.5rem 4rem;
    font-family: var(--font-serif);
    font-size: 1.0625rem;
    line-height: 1.65;
}

.page .back-link {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    font-style: italic;
    font-size: 1rem;
    color: var(--ink-soft);
    text-decoration: none;
    margin-bottom: 2.5rem;
}

.page .back-link img {
    width: 30px;
    height: 30px;
    border-radius: 22.5%;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.16), 0 4px 10px rgba(0, 0, 0, 0.12);
}

.page h1 {
    font-weight: 900;
    font-size: 2.6rem;
    letter-spacing: -0.015em;
    line-height: 1.05;
    margin-bottom: 1.5rem;
}

.page h2 {
    font-size: 1.2rem;
    font-weight: 700;
    margin: 2.25rem 0 0.4rem;
}

.page p,
.page li {
    color: var(--ink-soft);
    margin-bottom: 0.75rem;
}

.page ul {
    padding-left: 1.25rem;
}

.page a {
    color: var(--ink);
    text-decoration-color: var(--accent);
    text-decoration-thickness: 2px;
    text-underline-offset: 3px;
}

.page .updated {
    margin-top: 2.5rem;
    font-style: italic;
    font-size: 0.9rem;
    color: var(--ink-faint);
}

/* ---------- Press kit ---------- */

.page.press {
    max-width: 52rem;
}

.press .kicker {
    font-style: italic;
    font-size: 0.95rem;
    color: var(--ink-faint);
    margin-bottom: 0.5rem;
}

.press .lede {
    font-size: 1.2rem;
    color: var(--ink);
}

.press-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin: 1.5rem 0 2.5rem;
}

.page .press-button {
    display: inline-block;
    padding: 0.6rem 1.25rem;
    border-radius: 999px;
    background: var(--ink);
    color: var(--ground);
    font-family: var(--font-body);
    font-size: 0.95rem;
    font-weight: 600;
    text-decoration: none;
}

.page .press-button.secondary {
    background: transparent;
    color: var(--ink);
    box-shadow: inset 0 0 0 1.5px var(--rule);
}

.press figure img {
    display: block;
    width: 100%;
    height: auto;
    border-radius: 18px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.14), 0 8px 24px rgba(0, 0, 0, 0.12);
}

.press-hero {
    max-width: 26rem;
    margin: 0 auto 1rem;
}

.press-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 2rem 1.5rem;
    margin: 1.5rem 0 1rem;
}

.press-grid.three {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    align-items: end;
}

.press figcaption {
    margin-top: 0.75rem;
    font-size: 0.95rem;
    line-height: 1.5;
    color: var(--ink-soft);
}

.press figcaption strong {
    color: var(--ink);
}

.press .facts {
    display: grid;
    grid-template-columns: 9rem 1fr;
    gap: 0.4rem 1.25rem;
    margin-top: 0.75rem;
}

.press .facts dt {
    font-weight: 700;
}

.press .facts dd {
    color: var(--ink-soft);
}

@media (max-width: 640px) {
    .press-grid,
    .press-grid.three {
        grid-template-columns: minmax(0, 1fr);
    }

    .press .facts {
        grid-template-columns: 1fr;
        gap: 0.1rem;
    }

    .press .facts dd {
        margin-bottom: 0.5rem;
    }
}
