/*
  Shared styles for the standalone static content pages (about, how-to-play,
  types-of-clue, 404). These pages load without the WASM runtime so they are instant and
  fully crawlable; they reuse the design tokens and card chrome from privacy.html. Kept as
  one stylesheet rather than repeating the block in every page.
*/

/* The masthead face: a warm, newspaper-adjacent serif (SIL OFL, self-hosted in
   /fonts with its licence). One variable file carries every weight we use. */
@font-face {
    font-family: "Fraunces";
    font-style: normal;
    font-weight: 300 900;
    font-display: swap;
    src: url("/fonts/fraunces-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2212, U+FEFF, U+FFFD;
}

:root {
    /* The app's own indigo, given the page: a lavender-tinted canvas instead of
       neutral grey, ink leaning the same way, and the familiar #4f46e5 carrying
       links and actions. The in-app tokens (app.css) are deliberately unchanged. */
    --bg: #edecfa;
    --surface: #ffffff;
    --hairline: #dcdaf0;
    --ink: #1c1b33;
    --ink-dim: #676583;
    --accent: #4f46e5;

    /* Calls to action, tokenised so a future re-theme is a two-line change. */
    --cta-bg: #4f46e5;
    --cta-ink: #ffffff;

    --font-display: "Fraunces", Georgia, "Times New Roman", serif;
    --font-mono: ui-monospace, "Cascadia Mono", "SF Mono", Menlo, Consolas, monospace;

    /* Solution grid — mirrors the play grid tokens (app.css). Cells are light
       "paper" and blocks are dark in BOTH themes, so the grid reads the same as
       today's puzzle and never inverts (text must not follow the flipping --ink). */
    --cell-bg: #ffffff;
    --block-bg: #1f2733;
    --cell-ink: #16202e;
    --cell-num: #6b7686;
    --cell-selected: #ffe39a;
    --grid-line: #1f2733;
    --radius-lg: 18px;
    --shadow-md: 0 6px 18px rgba(0, 0, 0, .16);
}

@media (prefers-color-scheme: dark) {
    :root {
        --bg: #131120;
        --surface: #1c1a2f;
        --hairline: #322f4d;
        --ink: #ebe9f8;
        --ink-dim: #a19fc2;
        --accent: #918bff;

        /* The same purple as ever for the action fill, but with deep-indigo text:
           white on #7c75ff computes at 3.6:1 (below AA); this pair is 4.9:1. */
        --cta-bg: #7c75ff;
        --cta-ink: #17153a;

        /* Keep cells light and blocks dark in dark mode too (mirrors app.css). */
        --cell-bg: #e9edf4;
        --block-bg: #060a0f;
        --cell-ink: #16202e;
        --cell-num: #5d6878;
        --cell-selected: #f0c75a;
        --grid-line: #0a0e14;
    }
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    background: var(--bg);
    color: var(--ink);
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    line-height: 1.55;
    -webkit-text-size-adjust: 100%;
}

main {
    max-width: 42rem;
    margin: 0 auto;
    padding: calc(1.5rem + env(safe-area-inset-top)) 1.25rem
             calc(2.5rem + env(safe-area-inset-bottom));
}

.card {
    background: var(--surface);
    border: 1px solid var(--hairline);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
    padding: 1.5rem 1.5rem .5rem;
}

header {
    display: flex;
    align-items: center;
    gap: .8rem;
    margin-bottom: 1rem;
}

header img {
    width: 40px;
    height: 40px;
    border-radius: 9px;
}

/* Headings speak in the masthead face; running text stays the system sans. The
   size steps are deliberately big jumps: a flat 1.2:1 scale reads as one voice. */
h1 {
    margin: 0;
    font-family: var(--font-display);
    font-size: 1.85rem;
    font-weight: 700;
    line-height: 1.15;
    text-wrap: balance;
}

.updated {
    margin: 0;
    color: var(--ink-dim);
    font-size: .8rem;
}

/* Subtitle on a solution page naming the puzzle's ghost theme and the answers that share
   it. Sits under .updated in the header, so it reads as part of the masthead rather than
   as a section of its own. The answer list is dimmed a step below the label: the label is
   the point, the answers are the evidence. */
.sol-theme {
    margin: .3rem 0 0;
    font-size: .82rem;
    color: var(--ink-dim);
}

.sol-theme strong { color: var(--ink); }

.sol-theme span {
    display: block;
    margin-top: .1rem;
    font-size: .76rem;
    letter-spacing: .02em;
}

section {
    padding: 1rem 0;
    border-top: 1px solid var(--hairline);
}

section:first-of-type { border-top: none; }

h2 {
    margin: 0 0 .4rem;
    font-family: var(--font-display);
    font-size: 1.35rem;
    font-weight: 700;
    line-height: 1.2;
}

h3 {
    margin: 1rem 0 .3rem;
    font-family: var(--font-display);
    font-size: 1.05rem;
    font-weight: 600;
}

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

ul, ol { margin: 0 0 .6rem; padding-left: 1.25rem; }
li { margin: 0 0 .35rem; }

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

.lead { color: var(--ink-dim); }

/* Clue-type / example callout: the worked "clue → answer" line. Set the way the
   paper sets a clue: typewriter face on paper, the answer spaced out in caps. */
.example {
    margin: .4rem 0 0;
    padding: .55rem .75rem;
    background: var(--bg);
    border: 1px solid var(--hairline);
    border-radius: 10px;
    font-family: var(--font-mono);
    font-size: .88rem;
    line-height: 1.5;
}

.example .answer { font-weight: 800; letter-spacing: .14em; border-bottom: 2px solid currentColor; }

.signals {
    margin: .3rem 0 0;
    font-size: .85rem;
    color: var(--ink-dim);
}

.signals .tag {
    display: inline-block;
    margin-right: .35rem;
    padding: .05rem .4rem;
    border-radius: 6px;
    background: var(--cta-bg);
    color: var(--cta-ink);
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
}

.back {
    display: inline-block;
    margin-top: 1.25rem;
    font-size: .9rem;
}

/* Footer row of cross-links between the content pages. Retained for solution pages
   generated before the shared .site-footer below; new pages use .site-footer. */
.more-links {
    margin-top: 1.25rem;
    padding-top: 1rem;
    border-top: 1px solid var(--hairline);
    font-size: .9rem;
}

.more-links a { margin-right: 1rem; }

/* Shared page footer — identical markup on every static and generated page, so the
   whole site closes the same way: a wrapped row of cross-links plus the back-to-play
   link. Replaces the old per-page .more-links + .back pairing. */
.site-footer {
    margin-top: 2rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--hairline);
    text-align: center;
}

/* Primary cross-links: a wrapped, centered row, muted until hovered (mirrors the top nav). */
.footer-links {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: .45rem 1.35rem;
    font-size: .9rem;
}

.footer-links a {
    color: var(--ink-dim);
    font-weight: 600;
    transition: color .12s ease;
}

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

/* Secondary links (About / Privacy): their own line, smaller and quieter. */
.footer-meta { margin-top: .55rem; font-size: .8rem; }
.footer-meta a { font-weight: 500; }

/* Return-to-play link: the footer's call to action. Bolder accent, with a small
   leftward nudge on hover that echoes the back arrow. */
.site-footer .back {
    display: inline-block;
    margin-top: 1.4rem;
    font-size: .92rem;
    font-weight: 700;
    color: var(--accent);
    transition: transform .12s ease;
}

.site-footer .back:hover { text-decoration: none; transform: translateX(-3px); }

/* --- Editorial note ------------------------------------------------------- */
/* The "how this puzzle was checked" block at the foot of every solution page. It is
   accountability, not article text, so it sits below a rule and reads a size down:
   present for anyone who goes looking, never competing with the wordplay above. */
.editorial-note {
    margin-top: 1.75rem;
    padding-top: 1rem;
    border-top: 1px solid var(--hairline);
    color: var(--ink-dim);
    font-size: .88rem;
}

.editorial-note h2 {
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--ink-dim);
}

/* No ad-slot styles: the AdSense units and their loader were removed from all 16 pages
   that carried them, so .ad/.ad-label would be dead rules for markup that no longer
   exists. The previous version of this block (a unit hidden until data-ad-status="filled")
   is in git history if units come back; note when they do that hiding the .ad container
   itself deadlocks, because a display:none parent reports zero available width and AdSense
   will not render into a zero-width slot. ads.txt and app-ads.txt are deliberately kept:
   app-ads.txt is load-bearing for the Android app's AdMob banner, which is unaffected by
   any of this. */

/* --- Hub link grid (guide index) ----------------------------------------- */
/* Group label above a .hub grid, so eight-plus links read as a few small shelves
   rather than one undifferentiated wall. */
.hub-title {
    margin: 1.15rem 0 .45rem;
    font-size: .78rem;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-dim);
}

.hub {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
    gap: .7rem;
    margin: .4rem 0 0;
}

.hub a {
    display: block;
    padding: .7rem .8rem;
    background: var(--bg);
    border: 1px solid var(--hairline);
    border-radius: 12px;
}

.hub a:hover { border-color: var(--accent); text-decoration: none; }
.hub a strong { display: block; color: var(--ink); font-size: .95rem; }
.hub a span { display: block; margin-top: .15rem; color: var(--ink-dim); font-size: .82rem; }

/* --- Reference table (abbreviations, devices) ---------------------------- */
.table-wrap { overflow-x: auto; margin: .4rem 0 0; }

table {
    width: 100%;
    border-collapse: collapse;
    font-size: .9rem;
}

th, td {
    padding: .4rem .6rem;
    text-align: left;
    border-bottom: 1px solid var(--hairline);
    vertical-align: top;
}

th { font-weight: 700; color: var(--ink-dim); font-size: .8rem; text-transform: uppercase; letter-spacing: .03em; }
td code, .k { font-family: var(--font-mono); font-weight: 700; letter-spacing: .02em; white-space: nowrap; }

/* --- Glossary ------------------------------------------------------------- */
dl { margin: .4rem 0 0; }
dt { font-weight: 800; margin-top: .8rem; }
dt:first-child { margin-top: 0; }
dd { margin: .15rem 0 0; padding-left: 0; color: var(--ink); }

/* --- Site header / nav bar (shared across every static page) -------------- */
/* A slim sticky bar so a visitor who arrives on any page (usually straight from
   search) can reach the rest of the site. Links are absolute (/...) so the exact
   same markup also works from the /solutions/ subdirectory. */
.site-nav {
    position: sticky;
    top: 0;
    z-index: 20;
    display: flex;
    align-items: center;
    gap: .75rem 1rem;
    flex-wrap: wrap;
    padding: .55rem clamp(1rem, 4vw, 2.5rem);
    background: var(--surface);
    border-bottom: 1px solid var(--hairline);
}

.site-nav .brand {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.1rem;
    color: var(--ink);
}

.site-nav .brand:hover { text-decoration: none; }
.site-nav .brand img { width: 28px; height: 28px; border-radius: 7px; }

.site-nav-links {
    display: flex;
    align-items: center;
    gap: .3rem 1.1rem;
    flex-wrap: wrap;
    margin-left: auto;
    font-size: .9rem;
}

.site-nav-links a {
    color: var(--ink-dim);
    font-weight: 600;
    white-space: nowrap;
}

.site-nav-links a:hover { color: var(--ink); text-decoration: none; }

.site-nav-links a.cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
    padding: .4rem .85rem;
    border-radius: 999px;
    background: var(--cta-bg);
    color: var(--cta-ink);
}

.site-nav-links a.cta:hover { color: var(--cta-ink); filter: brightness(1.12); }

/* Google Play button in the header. Reuses the canonical .gp-cta look (below) but
   trimmed to sit inline at the nav bar's pill height, next to the Play CTA. The
   explicit white text/hover are needed to outrank the grey `.site-nav-links a` rule
   above (higher specificity than the base `.gp-cta` colour). */
.site-nav-links a.gp-cta,
.site-nav-links a.gp-cta:hover {
    margin: 0;
    padding: .35rem .85rem;
    border-radius: 999px;
    font-size: .9rem;
    color: var(--cta-ink);
}

.site-nav-links a.gp-cta .gp-mark { width: 1rem; height: 1rem; }

/* The Play + Google Play pills, grouped so they stay together. On desktop this is an
   invisible inline group (the pills read exactly as they did loose in the row); on mobile
   the group is forced onto its own line so the two pills always share a row. */
.site-nav-cta {
    display: inline-flex;
    align-items: center;
    gap: .3rem 1.1rem;
}

/* Mobile header: only the brand stays — pinned as a slim bar at the very top — while the
   guide links and CTA pills sit below it and scroll up off the top with the page. The
   brand is position:fixed (so it stays in every browser, unlike a scroll-driven
   animation), and the nav reserves top room so the links start just under the pinned bar.
   Links are tightened so the four guide links share one row, giving a 3-line header:
   brand, then links, then the Play / Get-it-on-Google-Play pills. */
@media (max-width: 600px) {
    .site-nav {
        position: static;          /* the bar itself scrolls away; only .brand stays put */
        justify-content: center;
        row-gap: .35rem;
        /* top padding clears the fixed brand bar sitting above the links */
        padding: calc(2.5rem + env(safe-area-inset-top)) .8rem .5rem;
        /* No divider above the title: the links/pills scroll away, so at rest the header
           and the page below read as one clean block (the pinned brand keeps its own line). */
        border-bottom: none;
    }

    .site-nav .brand {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        z-index: 30;
        justify-content: center;   /* centre the brand within its full-width bar */
        font-size: 1rem;
        /* Opaque surface fill covers content scrolling underneath; no border, so at rest
           the header reads as one clean block. When scrolled, the surface-vs-page colour
           difference alone marks the pinned bar. */
        background: var(--surface);
        padding: calc(.5rem + env(safe-area-inset-top)) .8rem .5rem;
    }

    .site-nav .brand img { width: 24px; height: 24px; }

    .site-nav-links {
        margin-left: 0;
        width: 100%;
        justify-content: center;
        gap: .35rem .55rem;
        font-size: .8rem;
    }

    /* Break the pill group onto its own row so Play + Google Play always share a line
       below the four guide links. */
    .site-nav-cta {
        flex-basis: 100%;
        justify-content: center;
        gap: .5rem;
    }

    .site-nav-links a.cta,
    .site-nav-links a.gp-cta {
        padding: .3rem .75rem;
        font-size: .8rem;
    }

    .site-nav-links a.gp-cta .gp-mark { width: .85rem; height: .85rem; }
}

/* --- Landing hero (home page) --------------------------------------------- */
.hero { text-align: center; }
.hero h1 { margin: .4rem 0 .5rem; font-size: clamp(2.1rem, 6vw, 2.75rem); font-weight: 600; line-height: 1.12; }
.hero .lead { max-width: 34rem; margin: 0 auto .9rem; font-size: 1.05rem; }

.btn-play {
    display: inline-block;
    margin: .3rem 0 .5rem;
    padding: .85rem 1.7rem;
    border-radius: 999px;
    background: var(--cta-bg);
    color: var(--cta-ink);
    font-size: 1.1rem;
    font-weight: 800;
    box-shadow: var(--shadow-md);
}

.btn-play:hover { text-decoration: none; filter: brightness(1.12); }

.hero-sub { margin: 0; color: var(--ink-dim); font-size: .85rem; }

/* --- Worked clues (homepage "Try three clues") ---------------------------- */
/* Each clue is a panel, with the working folded behind a <details> so the reader gets to
   try before they look. The content is in the markup either way, so this is a reading
   affordance rather than a way of hiding anything from a crawler. */
.worked {
    margin: .9rem 0 0;
    padding: 0;
    list-style: none;
    counter-reset: worked;
}

.worked > li {
    counter-increment: worked;
    margin: 0 0 .7rem;
    padding: .85rem 1rem;
    background: var(--bg);
    border: 1px solid var(--hairline);
    border-radius: 12px;
}

.worked-clue {
    margin: 0;
    font-family: var(--font-display);
    font-size: 1.05rem;
    font-weight: 600;
}

.worked-clue::before {
    content: counter(worked) ". ";
    color: var(--ink-dim);
    font-weight: 400;
}

.worked-clue .enum { font-family: var(--font-mono); font-size: .85rem; font-weight: 400; color: var(--ink-dim); }

.worked summary {
    margin-top: .55rem;
    color: var(--accent);
    font-size: .85rem;
    cursor: pointer;
}

.worked summary:hover { text-decoration: underline; }

.worked details p { margin: .55rem 0 0; font-size: .92rem; }

.worked-answer {
    font-family: var(--font-mono);
    letter-spacing: .04em;
}

.worked-cta { margin: 1rem 0 .8rem; }

/* --- Latest answers (homepage, generated) -------------------------------- */
/* Deliberately a list of one-liners rather than the .hub card grid: five rows of number
   and theme is a change log, and it should read as one. */
.latest {
    margin: .7rem 0 .6rem;
    padding: 0;
    list-style: none;
}

.latest li + li { border-top: 1px solid var(--hairline); }

.latest a {
    display: flex;
    gap: .6rem;
    align-items: baseline;
    justify-content: space-between;
    padding: .5rem .1rem;
}

.latest a:hover { text-decoration: none; }
.latest a:hover span { text-decoration: underline; }
.latest strong { color: var(--ink); font-family: var(--font-mono); font-size: .92rem; }
.latest span { color: var(--ink-dim); font-size: .9rem; text-align: right; }

.latest-updated { margin: 0; color: var(--ink-dim); font-size: .82rem; }

/* --- Hero clue teaser (home page) ------------------------------------------ */
/* One real clue with typeable answer cells: the product itself as the hero image.
   Progressive enhancement; without JS it's simply a set clue and six empty cells. */
.teaser {
    max-width: 26rem;
    margin: 1.1rem auto .9rem;
    padding: .9rem 1rem 1rem;
    background: var(--bg);
    border: 1px solid var(--hairline);
    border-radius: 12px;
}

.teaser-clue {
    margin: 0 0 .65rem;
    font-family: var(--font-display);
    font-size: 1.15rem;
    font-weight: 600;
}

.teaser-clue .enum { font-family: var(--font-mono); font-size: .9rem; font-weight: 400; color: var(--ink-dim); }

.teaser-boxes {
    display: flex;
    justify-content: center;
    gap: 4px;
}

.tcell {
    position: relative;
    width: 2.6rem;
    max-width: 13vw;
    /* Without this the inputs refuse to shrink and the row overflows the teaser
       panel by ~37px a side at 320px wide. */
    min-width: 0;
    aspect-ratio: 1 / 1;
    padding: 0;
    border: 1.5px solid var(--grid-line);
    border-radius: 5px;
    background: var(--cell-bg);
    color: var(--cell-ink);
    font-family: inherit;
    font-size: 1.3rem;
    font-weight: 800;
    text-align: center;
    text-transform: uppercase;
    caret-color: var(--accent);
    /* The cells stay paper in dark mode (they're the product's own cells), so the
       UA must not restyle them as dark form controls. */
    color-scheme: light;
}

.tcell:focus { outline: 2px solid var(--accent); outline-offset: 1px; }

.teaser.solved .tcell { background: var(--cell-selected); }

.teaser-msg { min-height: 1.3rem; margin: .55rem 0 0; font-size: .88rem; color: var(--ink-dim); }
.teaser.solved .teaser-msg { color: var(--ink); font-weight: 600; }

@media (prefers-reduced-motion: no-preference) {
    .teaser.wrong .teaser-boxes { animation: teaser-shake .3s ease; }
}

@keyframes teaser-shake {
    0%, 100% { transform: translateX(0); }
    25% { transform: translateX(-5px); }
    75% { transform: translateX(5px); }
}

/* The closing call-to-action section draws its own divider (the block-rule), so it
   drops the default section hairline. */
section.closer { border-top: none; }

/* --- Crossword-block divider ------------------------------------------------ */
/* A short row of dim squares standing in for a plain <hr>: the grid's block
   rhythm, whispered. Drawn from the theme's own muted ink (the literal paper/block
   colours read as a glaring barcode on a dark page). Sized to end on a square:
   six .5rem squares with .5rem gaps = 5.5rem. */
.block-rule {
    width: 5.5rem;
    height: .5rem;
    margin: .2rem auto 1.2rem;
    background: repeating-linear-gradient(90deg,
        var(--ink-dim) 0 .5rem,
        transparent .5rem 1rem);
    border-radius: 2px;
    opacity: .45;
}

/* --- Solution grid + annotated clue list (generated solution pages) ------ */
.sol-grid {
    display: grid;
    gap: 2px;
    margin: .4rem auto 0;
    background: var(--grid-line);
    border: 2px solid var(--grid-line);
    border-radius: 6px;
    width: fit-content;
    max-width: 100%;
    /* Cells are light "paper" in both themes; pin the light UA scheme so the
       grid never falls back to dark form-control rendering. Mirrors .grid. */
    color-scheme: light;
}

.sol-grid .c {
    position: relative;
    width: 1.7rem;
    height: 1.7rem;
    background: var(--cell-bg);
    color: var(--cell-ink);
    font-size: .95rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
}

.sol-grid .c.block { background: var(--block-bg); }

.sol-grid .c .n {
    position: absolute;
    top: 1px;
    left: 2px;
    font-size: .5rem;
    font-weight: 600;
    line-height: 1;
    color: var(--cell-num);
}

/* "Get it on Google Play" call to action (get-app page). Mirrors the in-app
   .gp-cta (Play.razor.css) but as a standalone anchor. */
.gp-cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
    gap: .5rem;
    margin: .2rem 0 .1rem;
    padding: .7rem 1.1rem;
    border-radius: 12px;
    background: var(--cta-bg);
    color: var(--cta-ink);
    font-weight: 700;
    text-decoration: none;
    transition: filter .1s ease;
}

.gp-cta:hover { filter: brightness(1.12); text-decoration: none; }
.gp-cta:active { filter: brightness(.94); }
.gp-cta .gp-mark { flex: 0 0 auto; width: 1.1rem; height: 1.1rem; fill: currentColor; }

/* One explained clue: "12 Across  CLUE (5) = ANSWER" then the wordplay. */
.clue { padding: .55rem 0; border-top: 1px solid var(--hairline); }
.clue:first-of-type { border-top: none; }
.clue .cn { font-weight: 800; }
.clue .ct { }
.clue .ca { font-family: var(--font-mono); font-weight: 800; letter-spacing: .08em; }
.clue .cw { display: block; margin-top: .1rem; color: var(--ink-dim); font-size: .87rem; }
.clue .badge {
    display: inline-block;
    margin-left: .35rem;
    padding: .02rem .4rem;
    border-radius: 6px;
    background: var(--bg);
    border: 1px solid var(--hairline);
    font-size: .7rem;
    font-weight: 700;
    color: var(--ink-dim);
}
