/* ==========================================================================
   icyhoty2k.github.io

   ONE stylesheet, no framework, no CDN. Every font is vendored in
   assets/fonts/ -- the site says it uses no third parties and that has to be
   literally true, which means no Google Fonts, no analytics, no embeds.

   Palette matches QuickImageViewer's site.css so the two read as one hand,
   and matches the Play developer art, which is generated from the same
   numbers.
   ========================================================================== */

@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('fonts/inter-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('fonts/inter-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}

:root {
    --bg:        #0f172a;
    --surface:   #1e293b;
    --surface-2: #172033;
    --border:    #2b3a52;
    --text:      #f8fafc;
    --muted:     #94a3b8;
    --accent:    #38bdf8;
    --accent-dk: #0284c7;
    --radius:    14px;
    --maxw:      1080px;
}

/* Light mode is a real mode, not an afterthought: a developer page gets opened
   from a Play listing on a phone in daylight as often as from a desktop at
   night. */
@media (prefers-color-scheme: light) {
    :root {
        --bg:        #f8fafc;
        --surface:   #ffffff;
        --surface-2: #eef2f7;
        --border:    #d7dee8;
        --text:      #0f172a;
        --muted:     #566579;
        --accent:    #0284c7;
        --accent-dk: #075985;
    }
}

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

html { scroll-behavior: smooth; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
    font-size: 17px;
    line-height: 1.65;
    -webkit-font-smoothing: antialiased;
}

.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 24px; }

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* --- header ------------------------------------------------------------- */

.sitenav {
    border-bottom: 1px solid var(--border);
    background: color-mix(in srgb, var(--bg) 88%, transparent);
    position: sticky;
    top: 0;
    z-index: 10;
    backdrop-filter: blur(8px);
}

.sitenav .wrap {
    display: flex;
    align-items: center;
    gap: 20px;
    height: 62px;
}

.sitenav .brand {
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--text);
    font-weight: 650;
    letter-spacing: -0.01em;
}

/* Height, not width. The tight mark is a tall narrow box (40 x 168 units), so
   fixing the width would squash it; fixing the height lets the width fall out
   of the aspect ratio and the gap beside the wordmark becomes the real gap. */
.sitenav .brand img { height: 26px; width: auto; display: block; }
.sitenav .brand picture { display: flex; }
.sitenav .spacer { flex: 1; }
.sitenav a.navlink { color: var(--muted); font-size: 0.95rem; }
.sitenav a.navlink:hover, .sitenav a.navlink[aria-current="page"] { color: var(--text); }

/* --- hero --------------------------------------------------------------- */

.hero { padding: 84px 0 56px; }

.hero-inner {
    display: flex;
    align-items: center;
    gap: 48px;
    flex-wrap: wrap;
}

.hero-mark {
    width: 132px;
    height: 132px;
    flex: none;
    filter: drop-shadow(0 0 26px color-mix(in srgb, var(--accent) 35%, transparent));
}

.hero h1 {
    margin: 0 0 6px;
    font-size: clamp(2.2rem, 6vw, 3.4rem);
    font-weight: 700;
    letter-spacing: -0.03em;
    line-height: 1.05;
}

/* The second line of the signature. Tracked out and in the accent: set solid
   and grey, a nine-letter word under a nine-letter word reads as one block.
   The tracking is what makes it a sub-line rather than a second title.

   clamp()ed like the heading above it, so the two scale together instead of
   the sub-line staying put while the title grows. */
.hero .productions {
    margin: 0 0 16px;
    font-size: clamp(0.78rem, 1.7vw, 1rem);
    font-weight: 500;
    letter-spacing: 0.34em;
    text-transform: uppercase;
    color: var(--accent);
}

.hero p.lead {
    margin: 0;
    max-width: 46ch;
    color: var(--muted);
    font-size: 1.12rem;
}

/* The row of glyphs, matching the Play header. Inline SVG so it inherits
   currentColor and needs no extra request. */
.glyphrow {
    display: flex;
    gap: 18px;
    margin-top: 22px;
    color: var(--muted);
}
.glyphrow svg { width: 26px; height: 26px; flex: none; }

/* --- sections ----------------------------------------------------------- */

section { padding: 30px 0 56px; }

h2 {
    font-size: 1.05rem;
    font-weight: 650;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--muted);
    margin: 0 0 22px;
}

/* --- statistics strip ---------------------------------------------------- */

/* PILLS, matching QuickImageViewer's own strip. A first version here was a grid
   of six large cells; next to the desktop site it read as a different product.
   Same shape, same wrap-and-centre behaviour, same value-then-label order.

   Icons are inline SVG rather than the emoji the desktop strip uses. Same
   reason the navigation was converted: an emoji is drawn by whichever vendor
   made the font, so a row of six is a row of six different illustration styles.

   Numbers, not charts. Six unrelated current values with no series behind them;
   a chart of those is a table wearing a costume, and it would cost a library on
   a site that promises no third parties. */
.statstrip {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px;
    margin: 6px 0;
}

.stat {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 9px 15px;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text);
    font-size: 0.9rem;
    line-height: 1;
    transition: border-color .15s ease, transform .15s ease;
}

.stat:hover {
    border-color: var(--accent);
    transform: translateY(-1px);
    text-decoration: none;
}

.stat svg {
    width: 15px;
    height: 15px;
    flex: none;
    color: var(--muted);
    stroke-linecap: round;
    stroke-linejoin: round;
}

.stat:hover svg { color: var(--accent); }

.stat-value {
    font-weight: 700;
    color: var(--accent);
    font-variant-numeric: tabular-nums;
}

.stat-label { color: var(--muted); font-size: 0.82rem; }

@media (max-width: 620px) {
    .statstrip { gap: 8px; }
    .stat { padding: 8px 12px; font-size: 0.85rem; }
}

/* --- product cards ------------------------------------------------------ */

.cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 20px;
}

.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    transition: border-color .18s ease, transform .18s ease;
}

.card:hover { border-color: var(--accent); transform: translateY(-2px); }

@media (prefers-reduced-motion: reduce) {
    .card { transition: none; }
    .card:hover { transform: none; }
}

/* The screenshot. A page about image software with no images on it was the
   whole reason the landing page read as dead -- and Google's own starter guide
   asks for images placed near the text they relate to.

   Fixed aspect and object-fit so a portrait phone shot and a landscape desktop
   shot sit in the same grid without one of them stretching. width/height are
   declared in the HTML so the browser reserves the space and the card does not
   jump as the image arrives.

   HEIGHT: AUTO IS LOAD-BEARING, AND aspect-ratio DOES NOT WORK WITHOUT IT.
   The <img> tags carry width/height attributes, which are presentational hints:
   this rule overrides the width one with width:100%, but if it declares no
   height at all then the HTML height attribute survives as the USED height. Both
   dimensions are then definite and `aspect-ratio` is ignored outright.

   That is not theoretical -- it shipped. The two cards rendered 504x563 and
   504x462 instead of 504x284, because their height attributes were 563 and 462.
   The desktop shot was cropped to a narrow portrait slice of a 2688x1436 frame,
   and the Android shot was upscaled 2x past its own source height, which is
   what made it look soft. Declaring height:auto lets the aspect-ratio win and
   both cards become 16/9 again. */
.card-shot {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    object-position: top center;
    background: var(--surface-2);
    border-bottom: 1px solid var(--border);
}

.card-body { padding: 24px 26px 22px; display: flex; flex-direction: column; flex: 1; }

.card h3 {
    margin: 0 0 4px;
    font-size: 1.3rem;
    letter-spacing: -0.02em;
}

.card .plat {
    color: var(--muted);
    font-size: 0.86rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    margin-bottom: 14px;
}

.card p { margin: 0 0 18px; color: var(--muted); }
.card .grow { flex: 1; }

.tags { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 18px; }

.tag {
    font-size: 0.8rem;
    color: var(--muted);
    border: 1px solid var(--border);
    background: var(--surface-2);
    border-radius: 999px;
    padding: 3px 11px;
}

.actions { display: flex; flex-wrap: wrap; gap: 10px; }

.btn {
    display: inline-block;
    padding: 9px 17px;
    border-radius: 9px;
    font-weight: 600;
    font-size: 0.95rem;
    border: 1px solid var(--border);
    color: var(--text);
}
.btn:hover { text-decoration: none; border-color: var(--accent); }

.btn.primary {
    background: var(--accent);
    border-color: var(--accent);
    color: #06121f;
}
.btn.primary:hover { background: var(--accent-dk); border-color: var(--accent-dk); color: #fff; }

/* --- callout ------------------------------------------------------------ */

.callout {
    border: 1px solid var(--border);
    border-left: 3px solid var(--accent);
    background: var(--surface);
    border-radius: var(--radius);
    padding: 22px 26px;
}
.callout h3 { margin: 0 0 8px; font-size: 1.15rem; }
.callout p  { margin: 0 0 14px; color: var(--muted); }
.callout ol { margin: 0 0 16px; padding-left: 20px; color: var(--muted); }
.callout li { margin-bottom: 6px; }
.callout :last-child { margin-bottom: 0; }

/* --- prose pages -------------------------------------------------------- */

.prose { max-width: 68ch; padding: 56px 0 72px; }
.prose h1 { font-size: 2.1rem; letter-spacing: -0.03em; margin: 0 0 6px; }
.prose .meta { color: var(--muted); margin: 0 0 34px; }
.prose h2 {
    text-transform: none;
    letter-spacing: -0.01em;
    font-size: 1.35rem;
    color: var(--text);
    margin: 38px 0 12px;
}
.prose p, .prose li { color: var(--muted); }
.prose strong { color: var(--text); font-weight: 600; }

/* --- footer ------------------------------------------------------------- */

footer {
    border-top: 1px solid var(--border);
    padding: 30px 0 46px;
    color: var(--muted);
    font-size: 0.92rem;
}
footer .row { display: flex; flex-wrap: wrap; gap: 18px; align-items: center; }
footer .spacer { flex: 1; }

@media (max-width: 620px) {
    .hero { padding: 56px 0 40px; }
    .hero-inner { gap: 28px; }
    .hero-mark { width: 96px; height: 96px; }

    /* TAP TARGETS. Measured on a 375px viewport: the nav links were 25px tall
       and the footer links 24px. Google's threshold is 48px, and a 24px target
       is a genuinely annoying thing to hit with a thumb.

       Padding rather than font-size, so the text stays the size it should be
       and only the hit area grows. Negative margin keeps the row from getting
       taller than it needs to look.

       Inline links inside paragraphs are left alone on purpose -- they are
       exempt from the guidance, and padding them would wreck the line spacing. */
    .sitenav a.navlink,
    .sitenav a.brand,
    footer .row a {
        padding-top: 11px;
        padding-bottom: 11px;
    }

    footer .row { gap: 10px 18px; margin: -11px 0; }
}

/* --- funding buttons: ONE look on every surface -------------------------- */
/*
   These deliberately mirror the shields.io "for-the-badge" sponsor badges in
   README.md, down to the two-tone split and the exact hex values, because the
   same pair of buttons appears on GitHub, on both websites, and anywhere else
   the work asks to be funded. One identity, three media.

   THE SITES CANNOT USE THE SHIELDS IMAGES THEMSELVES. An <img> pointing at
   img.shields.io is a third-party request from every visitor, and both sites
   promise in writing that they contact nobody. In README.md the same badge is
   fine, because GitHub proxies README images through its own camo servers and
   shields.io never sees a reader -- same picture, completely different
   consequence. So on the web the look is rebuilt in CSS, with inline SVG icons
   in place of the emoji shields renders.

   KEEP IN SYNC: this block is byte-identical in
   icyhoty2k.github.io/assets/site.css and QuickImageViewer/docs/site.css, and
   the colours match the badge URLs in README.md. Change one, change all three.
*/
.fundrow {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin: 0;
}

.fund {
    display: inline-flex;
    align-items: stretch;
    border-radius: 6px;
    overflow: hidden;
    color: #fff;
    font-weight: 700;
    font-size: 0.72rem;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    line-height: 1;
    transition: filter .18s ease, transform .18s ease;
}

.fund:hover {
    text-decoration: none;
    color: #fff;
    filter: brightness(1.12);
    transform: translateY(-1px);
}

.fund:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 2px;
}

/* Two segments, exactly as the badge draws them: the darker one carries the
   icon and the name, the brighter one carries the phrase. */
.fund .fund-k,
.fund .fund-v {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 13px 15px;
}

.fund svg {
    width: 15px;
    height: 15px;
    flex: none;
}

.fund.gh   .fund-k { background: #bf3a8c; }
.fund.gh   .fund-v { background: #ea4aaa; }
.fund.kofi .fund-k { background: #c94340; }
.fund.kofi .fund-v { background: #ff5e5b; }

@media (prefers-reduced-motion: reduce) {
    .fund { transition: none; }
    .fund:hover { transform: none; }
}
