/* blakemills.dev. Dark only (no light theme, no toggle), system fonts, no web fonts. Ported from docs/mockups/v6/style.css.
   The site's CSP allows only this file (and nojs.css): no inline styles anywhere, so every look is a class or an id here.
   Later tasks add their own parts (the Focus dialog, the warehouse screen, the pipeline tips). */
:root {
  color-scheme: dark;
  --bg: #100f0d; --panel: #181714; --panel-hi: #1d1b16; --code: #0c0b0a; --tip: #1c1b17;              /* backgrounds: page, card, card pointed at, code / poster, tip */
  --ink: #ebe8df; --text: #cfcbc0; --muted: #969286; --dim: #878378;                                     /* text: each at least 4.5:1 on every background (tests/unit/style.test.mjs) */
  --line: #2b2924; --line2: #3d3a32; --field: #6f6b60; --amber: #f0b44c; --violet: #a66bff; --bad: #f08a6c;
  --mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
  --sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --bar: 66px;                                                        /* the top bar's height */
}
* { box-sizing: border-box; }
html { scrollbar-gutter: stable; }                                    /* the page never jumps sideways when the scrollbar comes or goes */
body { margin: 0; background: var(--bg); color: var(--ink); font: 15px/1.5 var(--sans); min-height: 100vh; display: flex; flex-direction: column; -webkit-font-smoothing: antialiased; overflow-wrap: break-word; }
a { color: inherit; text-decoration-color: var(--muted); text-underline-offset: 3px; }
button { font: inherit; color: inherit; cursor: pointer; }
[hidden] { display: none !important; }                                /* hidden wins over the display a rule gives (a row, a card with a video, a year of the Writing list) */
:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
@keyframes rise { from { opacity: 0; transform: translateY(6px); } }
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: .001s !important; animation-delay: 0s !important; transition: none !important; } }

/* keyboard users skip the top bar */
.skip { position: absolute; left: 16px; top: -200px; z-index: 100; padding: 10px 16px; background: var(--panel); border: 1px solid var(--amber); border-radius: 10px; text-decoration: none; }
.skip:focus { top: 12px; }

/* ---------- the pipeline: behind the page on wide screens, a strip above the footer on a phone (public/js/pipeline/stage.mjs draws it and places what is below) ---------- */
#stage { position: fixed; inset: 0; width: 100%; height: 100%; z-index: 0; display: block; touch-action: pan-y; pointer-events: none; }
.strip { display: none; }                                             /* the phone's pipeline strip */
.strip #stage, .strip .lanes { position: absolute; inset: 0; z-index: auto; }
/* the icon at the start of each lane and the warehouse logo they merge into: dim, brighter as the pointer comes near (--lit, 0 to 1), bright when pointed at or focused */
.lanes { position: fixed; inset: 0; z-index: 2; pointer-events: none; }
.src, .wh { --lit: 0; position: absolute; display: grid; place-items: center; padding: 0; border: 1px solid var(--line); background: var(--panel); }
.src { border-radius: 11px; color: var(--ink); opacity: calc(.42 + .58 * var(--lit)); pointer-events: auto; text-decoration: none; cursor: default; transition: opacity .15s, border-color .15s; }
a.src { cursor: pointer; }
.src:hover, .src:focus-visible { opacity: 1; border-color: var(--muted); }
.src svg { width: 56%; height: 56%; }
.src[data-lane="website"] svg { width: 84%; height: auto; stroke-width: 1.7; }
.wh { border-radius: 14px; color: var(--muted); opacity: calc(.45 + .55 * var(--lit)); pointer-events: auto; transition: border-color .15s, color .15s, opacity .15s, transform .15s; }
.wh svg { width: 60%; height: 60%; }
.wh:hover, .wh:focus-visible { opacity: 1; color: var(--ink); border-color: var(--amber); transform: scale(1.04); }     /* the door to the tables screen */
.cbx { position: absolute; padding: 0; border: 0; border-radius: 4px; background: none; color: inherit; font: inherit; pointer-events: auto; cursor: pointer; }    /* the button over a lane's conform box (drawn on the canvas): as big as the box, nothing drawn of its own; the ring is the page's :focus-visible one */
@media (max-width: 940px), (pointer: coarse) { .cbx::after { content: ""; position: absolute; left: 50%; top: 50%; width: 44px; height: 44px; transform: translate(-50%, -50%); } }   /* a 44px place to tap, as the lane icons have; the lanes are 50px apart in the strip and the icons are far to its left */
/* what a source is: a small card beside its icon (shown on hover or focus) */
.stip { position: fixed; z-index: 60; pointer-events: none; width: max-content; max-width: min(340px, calc(100vw - 16px)); padding: 10px 12px; background: var(--tip); border: 1px solid var(--line2); border-radius: 10px; box-shadow: 0 10px 30px rgba(0, 0, 0, .55); text-align: left; font: 12px/1.45 var(--mono); color: var(--ink); }
.stip .h { font: 500 14px/1.35 var(--sans); }
.stip .d { margin-top: 3px; font: 13px/1.5 var(--sans); color: var(--text); }
.stip .go { margin-top: 7px; font: 11.5px var(--mono); color: var(--dim); }
.stip .eg { margin-top: 7px; font: 11.5px/1.5 var(--mono); color: var(--dim); white-space: pre; }   /* an example, two lines: never wrapped */
/* a conform box's card reads like a stored procedure: its name, a SQL comment, the call, the row it inserts and "..." (mono; the lines wrap only on a screen too narrow for them) */
.stip.sp { max-width: min(540px, calc(100vw - 16px)); }
.stip.sp .h { font: 500 13px/1.35 var(--mono); }
.stip.sp .d { margin-top: 4px; font: 11.5px/1.5 var(--mono); color: var(--dim); overflow-wrap: anywhere; }
.stip.sp .eg { white-space: pre-wrap; overflow-wrap: anywhere; color: var(--text); }
/* what a dot is (pipeline/hover.mjs): its head, a tag, and the payload, the row or the count update as code. Never wider than 320px, never taller than the room beside its dot (a long payload is cut, not scrolled) */
.dtip { max-width: min(320px, calc(100vw - 16px)); overflow: hidden; pointer-events: auto; cursor: default; animation: tipin .12s ease-out; }   /* (it takes the pointer: a tap on it never reaches what is under it. Its height is cut to its room by hover.mjs) */
@keyframes tipin { from { opacity: 0; transform: translateY(3px); } }
.dtip .h em { font-style: normal; font-weight: 400; color: var(--muted); }
.dtip .k { display: flex; align-items: center; gap: 7px; margin-top: 3px; color: var(--muted); }
.dtip .sh { flex: none; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }   /* grey (the tag's colour) for a raw payload; hover.mjs gives a row its kind's colour */
.dtip .tn { margin-top: 8px; font-size: 11px; color: var(--dim); }
.dtip pre { margin: 8px 0 0; padding: 8px 10px; max-height: 13.5em; overflow: hidden; background: var(--code); border: 1px solid var(--line); border-radius: 8px; font: 11.5px/1.5 var(--mono); color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; }
.dtip .tn + pre { margin-top: 3px; }

/* ---------- the top bar: the BAM. logo, the controls, the Projects / Writing links ---------- */
#top { position: fixed; left: 0; right: 0; top: 0; z-index: 44; height: var(--bar); display: flex; align-items: center; gap: 12px; padding: 0 22px 0 16px;
  background: linear-gradient(var(--bg) calc(100% - 8px), rgba(16, 15, 13, 0)); pointer-events: none; }        /* solid behind every control (the mockup's 62% let scrolled text show through Projects / Writing, worst on a phone's two-row bar), then a short fade */
#top > * { pointer-events: auto; }
#homeLogo { flex: none; display: block; width: 60px; height: 44px; padding: 2px 0; color: var(--ink); text-decoration: none; transition: transform .2s ease; }
#homeLogo svg { display: block; width: 100%; height: 100%; stroke-width: 1.2; }        /* the mark is the whole thing: no box around it */
#homeLogo:hover, #homeLogo:focus-visible { transform: translateY(-3px); }               /* it stands up a little when you point at it */
.ctl { display: flex; align-items: center; gap: 12px; }
.mini { position: relative; border: 1px solid var(--line2); background: none; border-radius: 8px; padding: 1px 10px; font: 12px var(--mono); color: var(--muted); transition: color .15s, border-color .15s; }
.mini:hover { color: var(--ink); border-color: var(--muted); }
.mini[aria-pressed="true"] { color: var(--ink); border-color: var(--muted); }
.info { position: relative; font: 12px var(--mono); color: var(--muted); }
.info summary { position: relative; cursor: pointer; list-style: none; text-decoration: underline; text-underline-offset: 3px; }
.info summary::-webkit-details-marker { display: none; }
.info summary:hover { color: var(--ink); }
.info p { position: absolute; left: 0; top: 150%; z-index: 40; width: min(270px, 80vw); margin: 0; padding: 10px 14px; background: var(--tip); border: 1px solid var(--line2); border-radius: 12px; font: 13px/1.5 var(--sans); color: #d6d2c6; box-shadow: 0 10px 30px rgba(0, 0, 0, .5); }
#topnav { margin-left: auto; display: flex; align-items: center; gap: 24px; }
#topnav a { display: inline-flex; align-items: center; min-height: 44px; color: var(--muted); text-decoration: none; font-size: 14.5px; transition: color .15s; }
#topnav a:hover { color: var(--ink); }
#topnav a[aria-current] { color: var(--ink); text-decoration: underline; text-underline-offset: 7px; text-decoration-color: var(--amber); text-decoration-thickness: 1.5px; }

/* ---------- the page ---------- */
#view { position: relative; z-index: 1; flex: 1; display: flex; flex-direction: column; padding: 88px 20px 70px; }
.enter:not(:has(.card)) { animation: rise .25s; }                     /* a page the router swaps in rises the way cards do (a page with cards lets them do it) */
h1 { margin: 0; font-size: 36px; font-weight: 500; letter-spacing: -.025em; }
h1[tabindex="-1"]:focus-visible { outline: none; }                    /* the router moves focus to the new page's heading so a screen reader says where you are; a heading is not a control, so no ring */
.lcol { width: min(760px, 100%); margin: 0 auto; }
.lcol > h1, .lhead h1 { font-size: 34px; }
.lhead { display: flex; align-items: center; gap: 8px 6px; }                  /* the title, then (made by the page's script) the glass and the tag chip: one row, nothing wraps, so nothing moves when the box opens */
.lhead h1 { flex: none; margin-right: 4px; }
.lede { margin: 6px 0 22px; color: var(--muted); font-size: 16px; }
.empty, .none { margin: 26px 0; color: var(--muted); }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }          /* for a screen reader only */
mark { color: var(--ink); background: rgba(240, 180, 76, .3); border-radius: 3px; padding: 0 1px; }                       /* a word found by the search */
p:has(> .back) { margin: 0; }
.back { display: inline-flex; align-items: center; min-height: 32px; margin-bottom: 6px; color: var(--muted); font-size: 14px; text-decoration: none; transition: color .15s; }
.back:hover { color: var(--ink); }

/* ---------- home: one calm column in the middle ---------- */
.home { width: min(840px, 100%); margin: auto; padding: 8px 0 24px; text-align: center; }
.tagline { margin: 2px 0 14px; font-size: 24px; font-weight: 500; letter-spacing: .01em; color: var(--amber); }
.spotlight, .find { margin-top: 14px; }
.home :is(.spotlight, .find) > h2 { margin: 0 0 10px; font: 500 11px var(--sans); letter-spacing: .09em; text-transform: uppercase; color: var(--muted); }
.spotlight .btns, .find ul { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin: 0; padding: 0; list-style: none; }
.home :where(.spotlight, .find) .btn { display: inline-flex; align-items: center; min-height: 44px; padding: 0 18px; border: 1px solid var(--line); border-radius: 999px; background: var(--panel); font-size: 15px; text-decoration: none; transition: border-color .15s, background-color .15s; }
.home :where(.spotlight, .find) .btn:hover { border-color: var(--muted); }
.find .btn { min-height: 38px; padding: 0 16px; font-size: 14px; }
/* the standouts: amber for projects, violet (the Blog lane's colour) for writing */
.spotlight .btn { --acc: 240, 180, 76; border-color: rgba(var(--acc), .5); background: rgba(var(--acc), .08); }
.spotlight.writ .btn { --acc: 166, 107, 255; }
.spotlight .btn:hover { border-color: rgb(var(--acc)); background: rgba(var(--acc), .16); }
.spotlight p { margin: 0; }
/* the one opened under the buttons (below) is filled in its colour */
.spotlight .btn[aria-current], .spotlight .btn[aria-current]:hover { border-color: rgb(var(--acc)); background: rgb(var(--acc)); color: #1a1409; }
.detail { width: min(680px, 100%); margin: 0 auto; }
.detail > .card { margin-top: 22px; scroll-margin-top: calc(var(--bar) + 12px); }    /* (scrolled to, it sits just under the top bar) */
.detail > .card:focus { outline: none; }                              /* (focus goes to it so the next Tab is inside it; the card is not a control, so no ring) */
.all { display: inline-flex; align-items: center; min-height: 26px; margin-top: 6px; font-size: 13px; color: var(--dim); text-decoration: none; transition: color .15s; }
.all:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 4px; text-decoration-color: var(--line2); }

/* ---------- cards: a project (list or page) and a post ---------- */
.card { position: relative; margin-top: 16px; text-align: left; background: var(--panel); border: 1px solid var(--line); border-radius: 14px; padding: 20px 22px; animation: rise .25s; }
.card.feat { border-color: rgba(240, 180, 76, .38); }
.ctitle { margin: 0; font-size: 19px; font-weight: 500; letter-spacing: 0; line-height: 1.3; display: flex; justify-content: space-between; gap: 12px; align-items: baseline; }
.ctitle small { flex: none; color: var(--muted); font: 13px var(--mono); }
#card .ctitle { font-size: 26px; letter-spacing: -.015em; line-height: 1.25; }        /* an item's own page: its title is the page's h1 */
.card.post .ctitle { display: block; }
.card.post:where(:not(#card)) .ctitle { font-size: 21px; }
.card p { margin: 8px 0 0; color: var(--text); }
.card .meta { margin-top: 6px; font: 12.5px var(--mono); color: var(--muted); }
.card.post p, .card .story p { margin: 14px 0 0; line-height: 1.65; }
.card p.sn { margin: 10px 0 0; font: 12.5px/1.5 var(--mono); color: var(--dim); overflow-wrap: anywhere; }                 /* the line of the write-up a search found its word in */
.card :is(h2, h3, h4, h5, h6):not(.ctitle) { margin: 26px 0 0; font: 500 11px var(--sans); letter-spacing: .09em; text-transform: uppercase; color: var(--muted); }
.card ul.li, .card ol.li { margin: 12px 0 0; padding-left: 1.4em; }
.card .li li { padding: 3px 0; color: var(--text); line-height: 1.6; }
.card strong { font-weight: 600; color: var(--ink); }
.card p a, .card li a { color: var(--ink); text-decoration-color: var(--line2); transition: text-decoration-color .15s; }
.card p a:hover, .card li a:hover { text-decoration-color: var(--amber); }
.card code { padding: 1px 6px; font: .88em var(--mono); background: rgba(255, 255, 255, .06); border-radius: 5px; }
pre.code { margin: 14px 0 0; padding: 12px 14px; background: var(--code); border: 1px solid var(--line); border-radius: 10px; overflow-x: auto; font: 13px/1.6 var(--mono); }
pre.code code { padding: 0; background: none; font: inherit; white-space: pre; }   /* every line break and space stays as typed; a long line scrolls inside its box */
pre.code .k { color: #e69a5e; } pre.code .s { color: #9bc79a; } pre.code .n { color: #86aef5; } pre.code .c { color: var(--dim); font-style: italic; }
.card .tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.btns { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.card .btn { display: inline-flex; align-items: center; min-height: 38px; border: 1px solid var(--line2); border-radius: 10px; padding: 0 14px; text-decoration: none; font-size: 14px; transition: border-color .15s; }
.card .btn:hover { border-color: var(--ink); }
.tag { position: relative; display: inline-block; padding: 2px 8px; font: 11.5px var(--mono); color: var(--muted); background: none; border: 1px solid var(--line2); border-radius: 6px; text-decoration: none; transition: color .15s, border-color .15s; }
a.tag:hover { color: var(--ink); border-color: var(--violet); }

/* the demo video: a poster that loads nothing from YouTube until it is pressed; then the player takes the card's full width, above the text */
.card.has-video { display: grid; grid-template-columns: minmax(0, 1fr) 260px; gap: 22px; align-items: start; }
.card.has-video .vid { order: 2; }
.card.has-video.playing { grid-template-columns: minmax(0, 1fr); }
.card.has-video.playing .vid { order: -1; }
.poster { position: relative; overflow: hidden; width: 100%; aspect-ratio: 16 / 9; display: grid; place-content: center; justify-items: center; gap: 6px; padding: 10px; text-align: center; background: var(--code); border: 1px solid var(--line2); border-radius: 10px; transition: border-color .15s; }
.poster:hover { border-color: var(--amber); }
.pimg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: .4; }
.poster::after { content: ""; position: absolute; inset: 0; background: var(--code); opacity: .5; }         /* a scrim over the picture (after it, under the words): the label stays readable over a bright one */
.pbtn, .plabel, .pnote { position: relative; z-index: 1; }
.pbtn { width: 44px; height: 44px; border-radius: 50%; border: 1.5px solid var(--amber); color: var(--amber); display: grid; place-items: center; font-size: 15px; padding-left: 3px; background: rgba(12, 11, 10, .6); }
.plabel { font-size: 13px; color: var(--ink); }
.pnote { padding: 1px 8px; font: 11px var(--mono); color: var(--dim); background: var(--code); border-radius: 999px; }   /* (its own background: readable over any picture) */
.player iframe { display: block; width: 100%; aspect-ratio: 16 / 9; border: 1px solid var(--line2); border-radius: 10px; background: var(--code); animation: rise .25s; }
.wlink { display: inline-flex; align-items: center; min-height: 32px; margin-top: 4px; font: 12.5px var(--mono); color: var(--muted); text-decoration: none; transition: color .15s; }
.wlink:hover { color: var(--ink); }
.cards .card .player { position: relative; z-index: 1; }

/* Focus (Task 8 makes it work) */
.ctools { display: flex; justify-content: flex-end; margin: -4px 0 8px; }
.focusbtn { position: relative; display: inline-flex; align-items: center; gap: 7px; padding: 4px 12px 4px 10px; font: 12px var(--mono); color: var(--muted); background: none; border: 1px solid var(--line2); border-radius: 999px; transition: color .3s, border-color .3s; }
.focusbtn svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.focusbtn:hover { color: var(--ink); border-color: var(--amber); }

/* the Focus dialog: the whole screen, one reading column, nothing else. It grows out of the card (focus.mjs animates its clip-path); the page shows around it until it has,
   so it has no backdrop of its own. */
html:has(dialog.focusdlg[open]) { overflow: hidden; }
dialog.focusdlg { position: fixed; inset: 0; width: 100%; height: 100%; max-width: none; max-height: none; margin: 0; border: 0; border-radius: 0; background: var(--bg); overflow: auto; overscroll-behavior: contain; }
dialog.focusdlg[open] { animation: none; }
dialog.focusdlg::backdrop { background: none; }
.focusdlg .fx { position: fixed; top: 20px; right: 30px; z-index: 3; display: inline-flex; align-items: center; gap: 10px; padding: 6px 14px; font: 12.5px var(--mono); color: var(--muted); background: var(--panel); border: 1px solid var(--line2); border-radius: 999px; transition: color .3s, border-color .3s; }
.focusdlg .fx:hover { color: var(--ink); border-color: var(--amber); }
.focusdlg kbd { font: 11px var(--mono); color: var(--dim); border: 1px solid var(--line2); border-radius: 5px; padding: 0 5px; }
.focusdlg .fcol { width: min(740px, calc(100% - 48px)); margin: 0 auto; padding: 88px 0 140px; }
.focusdlg .card { display: block; margin: 0; padding: 0; background: none; border: 0; border-radius: 0; animation: none; font-size: 18px; line-height: 1.75; }
.focusdlg .card.has-video .vid { margin-bottom: 30px; }
.focusdlg .card .ctitle { font-size: clamp(28px, 4.2vw, 40px); line-height: 1.2; letter-spacing: -.02em; }
.focusdlg .card .ctitle small { font-size: 15px; }
.focusdlg .card p { margin: 20px 0 0; color: #d6d2c6; line-height: 1.75; }
.focusdlg .card .meta { margin-top: 10px; font-size: 13.5px; }
.focusdlg .card :is(h2, h3, h4, h5, h6):not(.ctitle) { margin-top: 40px; }
.focusdlg .card .story p { margin-top: 12px; }
.focusdlg pre.code { margin-top: 20px; padding: 16px 18px; font-size: 14.5px; }
.focusdlg .card .tags { margin-top: 18px; }
.focusdlg .card .btns { margin-top: 28px; }
.focusdlg .card .ask { font-size: 15px; margin-top: 30px; }

/* the like button and "Questions or corrections? Send me a message" under a post (Task 9 makes them work) */
.engage { margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--line); }
.likebtn { display: inline-flex; align-items: center; gap: 8px; min-height: 38px; border: 1px solid var(--line2); background: none; border-radius: 999px; padding: 0 16px; font-size: 14px; color: var(--ink); transition: border-color .15s, color .15s; }
.likebtn svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linejoin: round; }
.likebtn:hover { border-color: var(--amber); }
.likebtn[aria-pressed="true"] { border-color: var(--amber); color: var(--amber); }
.likebtn[aria-pressed="true"] svg { fill: var(--amber); }
.ct { margin-left: 10px; padding-left: 10px; border-left: 1px solid var(--line2); font: 11.5px var(--mono); color: var(--muted); font-variant-numeric: tabular-nums; }
.ct[hidden] { display: none; }
/* the count badge (badges.mjs): the Like count's look on a Spotlight or Find me button, a project card's title and a Writing row, once the all-time count is 5 or more. It is added to the line it is on and
   taken out again when the count falls: it reserves no room, so nothing moves for a badge that is not there. Its text is AA on every background it sits on (tests/unit/badges.test.mjs). */
.ct[data-badge] { display: inline-block; white-space: nowrap; font-weight: 400; text-shadow: none; }                  /* (a title it sits in may glow or be bold: the number does not) */
.spotlight .btn .ct { color: var(--text); border-left-color: rgba(var(--acc), .5); }                                  /* (on the accent's faint tint, --muted is under 4.5:1 once it is pointed at) */
.spotlight .btn[aria-current] .ct, .spotlight .btn[aria-current]:hover .ct { color: #1a1409; border-left-color: rgba(26, 20, 9, .4); }       /* (the open one is filled with the accent: the same dark ink as its label) */
.plist li:is(:hover, :focus-within) .ct { color: #bdb9ad; }                                                           /* (the row lights up: its date and minutes go to this grey, so the number follows) */
.card .ask { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; margin-top: 18px; font-size: 14px; color: var(--muted); }
.linkish { border: 0; background: none; padding: 0; color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.card .ask .linkish { min-height: 32px; padding: 0 13px; font-size: 13px; color: #aaa69a; text-decoration: none; border: 1px solid var(--line2); border-radius: 999px; transition: color .4s ease, border-color .4s ease, background-color .4s ease; }
.card .ask .linkish:hover, .card .ask .linkish:focus-visible { color: var(--ink); border-color: #55514a; background: rgba(255, 255, 255, .04); }

/* ---------- the Projects list: the whole card is the link (its title link is stretched over it); the poster, tags and buttons keep their own job ---------- */
.cards > .card { cursor: pointer; transition: transform .4s cubic-bezier(.2, .7, .2, 1), border-color .4s, background-color .4s, box-shadow .4s, opacity .4s; }
.cards a.tl { color: inherit; text-decoration: none; transition: color .3s ease, text-shadow .3s ease; }
.cards a.tl::after { content: ""; position: absolute; inset: 0; border-radius: 14px; }
.cards a.tl:focus-visible { outline: none; }
.cards a.tl:focus-visible::after { outline: 2px solid var(--amber); outline-offset: 2px; }
.cards .card :is(.poster, .tag, .btn) { position: relative; z-index: 1; }
/* the card you point at (or tab to) lifts, glows amber, grows a bar on its left edge, its title lights up, and the others step back */
.cards > .card::before { content: ""; position: absolute; left: -1px; top: 16px; bottom: 16px; width: 3px; border-radius: 3px; background: var(--amber); transform: scaleY(0); opacity: 0; transition: transform .45s cubic-bezier(.2, .7, .2, 1), opacity .3s; pointer-events: none; }
.cards .ctitle { transition: color .5s ease, text-shadow .5s ease; }
.cards > .card:focus-within { transform: translateY(-4px); border-color: rgba(240, 180, 76, .75); background-color: var(--panel-hi); box-shadow: 0 14px 44px rgba(0, 0, 0, .5), 0 0 34px rgba(240, 180, 76, .12); }
.cards > .card:focus-within::before { transform: scaleY(1); opacity: 1; }
.cards > .card:focus-within .ctitle { color: #fff; text-shadow: 0 0 20px rgba(255, 255, 255, .22); }
.cards:has(> .card:focus-within) > .card:not(:focus-within) { opacity: .5; }
@media (hover: hover) {
  .cards > .card:hover { transform: translateY(-4px); border-color: rgba(240, 180, 76, .75); background-color: var(--panel-hi); box-shadow: 0 14px 44px rgba(0, 0, 0, .5), 0 0 34px rgba(240, 180, 76, .12); }
  .cards > .card:hover::before { transform: scaleY(1); opacity: 1; }
  .cards > .card:hover .ctitle { color: #fff; text-shadow: 0 0 20px rgba(255, 255, 255, .22); }
  .cards:has(> .card:hover) > .card:not(:hover) { opacity: .5; }
}
@media (prefers-reduced-motion: reduce) { .cards > .card:hover, .cards > .card:focus-within { transform: none; } }

/* ---------- the Writing list: rows grouped by year; the whole row is the link, the tags sit above it ---------- */
.yr { margin: 28px 0 0; font: 500 11px var(--sans); letter-spacing: .09em; text-transform: uppercase; color: var(--muted); }
.plist { list-style: none; margin: 8px 0 0; padding: 0; border-bottom: 1px solid var(--line); }     /* (the line under the last row is the list's own: the last row may be hidden) */
/* The row and its link are the same grid, so the link is a real box (a display: contents link cannot take keyboard focus) and its parts line up with the tags under it */
.plist li, .plist li > a { display: grid; grid-template-columns: 112px minmax(0, 1fr) auto; gap: 4px 18px; align-items: baseline; }
.plist li { position: relative; padding: 16px 4px; border-top: 1px solid var(--line); }
.plist li > a { grid-column: 1 / -1; text-decoration: none; }
.plist li > a::after { content: ""; position: absolute; inset: 0; }
.plist li > a:focus-visible { outline: none; }
.plist li > a:focus-visible::after { outline: 2px solid var(--amber); outline-offset: -2px; border-radius: 6px; }
.plist .d { font: 12.5px var(--mono); color: var(--muted); }
.plist .t { font-size: 17px; font-weight: 500; color: #b4b0a4; }
.plist .g { font: 12px var(--mono); color: var(--dim); white-space: nowrap; }
.plist .s { grid-column: 2 / 4; color: var(--muted); font-size: 14px; }
.plist .sn { grid-column: 2 / 4; margin: 0; font: 12.5px/1.5 var(--mono); color: var(--dim); overflow-wrap: anywhere; }       /* the line of the post a search found its word in (a sibling of the link, so the link keeps its name) */
.plist .tg { grid-column: 2 / 4; position: relative; z-index: 1; display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; pointer-events: none; }
.plist .tg .tag { pointer-events: auto; }                             /* the space beside the chips belongs to the row link; the chips keep their own */
.plist li.feat .t::before { content: ""; display: inline-block; width: 7px; height: 7px; margin-right: 9px; border-radius: 50%; background: var(--violet); vertical-align: 2px; }
/* on hover the whole row lights up, quickly: from a dim grey up to white */
.plist :is(.d, .t, .g, .s, .sn, .tag) { transition: color .4s ease, text-shadow .4s ease, border-color .4s ease; }
.plist li:is(:hover, :focus-within) .t { color: #fff; text-shadow: 0 0 22px rgba(255, 255, 255, .32); }
.plist li:is(:hover, :focus-within) :is(.d, .g) { color: #bdb9ad; }
.plist li:is(:hover, :focus-within) .s { color: #dcd8cc; }
.plist li:is(:hover, :focus-within) .sn { color: var(--muted); }
.plist li:is(:hover, :focus-within) .tag { color: #bdb9ad; border-color: #55514a; }
.plist li .tag:hover { color: var(--ink); border-color: var(--violet); }

/* ---------- search and tags on the two lists: the glass beside the title, the box that slides out of it, the chip of the tag that is on (the page's script makes all of these) ---------- */
.finder { display: flex; align-items: center; flex: none; min-width: 0; min-height: 36px; }
.sbtn { display: grid; place-items: center; flex: none; width: 36px; height: 36px; padding: 0; border: 0; border-radius: 10px; background: none; color: var(--muted); transition: color .25s, background-color .25s; }
.sbtn svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }
.sbtn:hover, .sbtn[aria-expanded="true"] { color: var(--ink); background: rgba(255, 255, 255, .05); }
.qbox { flex: none; width: 0; height: 36px; margin-left: 0; padding: 0; opacity: 0; visibility: hidden; font: 15px var(--sans); color: var(--ink); background: var(--panel); border: 1px solid transparent; border-radius: 10px; appearance: none;
  transition: width .35s cubic-bezier(.2, .7, .2, 1), margin .35s, padding .35s, opacity .25s, border-color .25s, visibility 0s .35s; }
.finder.open .qbox { width: 300px; margin-left: 8px; padding: 0 12px; opacity: 1; visibility: visible; border-color: var(--field);
  transition: width .35s cubic-bezier(.2, .7, .2, 1), margin .35s, padding .35s, opacity .25s, border-color .25s; }
.qbox:focus-visible { outline: 2px solid transparent; outline-offset: 2px; box-shadow: 0 0 0 3px rgba(240, 180, 76, .16); }
.finder.open .qbox:focus-visible { border-color: var(--amber); }           /* (as specific as the open rule above, which would otherwise keep the resting edge) */
.fchip { position: relative; display: inline-flex; align-items: center; gap: 7px; flex: 0 1 auto; min-width: 0; margin-left: 2px; padding: 4px 10px; font: 12px var(--mono); color: var(--ink); text-decoration: none;
  background: rgba(166, 107, 255, .18); border: 1px solid var(--violet); border-radius: 999px; transition: background-color .2s; }
.fchip:hover { background: rgba(166, 107, 255, .3); }
.fchip span:first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }                    /* a very long tag in the address stays on its line */

/* A page opened at an address with a tag (/blog/?tag=Kafka) is marked by /js/early.js before its first paint; its list is kept back (an empty space, never the whole list) until lists.mjs has filtered it and
   taken the mark off. If the script never comes the list is shown after 1.5 s. The delay is !important and more specific than the reduced-motion rule, which would otherwise show the list at once. */
.tagged :is(.cards, .plist, h2.yr) { visibility: hidden; animation: reveal 0s 1.5s forwards; animation-delay: 1.5s !important; }
@keyframes reveal { to { visibility: visible; } }

/* ---------- the contact pop-up (contact-ui.mjs makes it work) ---------- */
dialog { border: 1px solid var(--line2); border-radius: 16px; background: var(--panel); color: var(--ink); padding: 0; width: min(460px, calc(100vw - 32px)); max-height: calc(100vh - 32px); max-height: calc(100dvh - 32px); overflow: auto; overscroll-behavior: contain; }
html:has(dialog#contactDialog[open]) { overflow: hidden; }          /* (the page behind does not scroll under the pop-up. The scrollbar's gutter stays reserved (an empty strip under the backdrop), so the content behind does not move: as under Focus, above) */
dialog::backdrop { background: rgba(6, 6, 5, .82); }
dialog[open] { animation: rise .25s; }
.dwrap { padding: 20px 22px 18px; text-align: left; }
.dhead { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; margin-bottom: 16px; }
.dhead h2 { margin: 0; font-size: 19px; font-weight: 500; }
.x { border: 1px solid var(--line2); background: none; border-radius: 8px; width: 36px; height: 36px; flex: none; color: var(--muted); }
.x:hover { color: var(--ink); border-color: var(--muted); }
dialog label { display: grid; gap: 6px; margin-bottom: 14px; font-size: 13px; color: var(--muted); }
dialog input, dialog textarea { width: 100%; font: 15px/1.4 var(--sans); color: var(--ink); background: var(--bg); border: 1px solid var(--field); border-radius: 10px; padding: 9px 12px; }          /* (--field: a control's edge is at least 3:1 on the panel, WCAG 1.4.11) */
dialog input:focus, dialog textarea:focus { outline: 2px solid transparent; outline-offset: 2px; border-color: var(--amber); box-shadow: 0 0 0 3px rgba(240, 180, 76, .16); }          /* (the clear outline turns into the system's in forced colours, where border and shadow are dropped) */
dialog :is(input, textarea)[aria-invalid="true"] { border-color: var(--bad); }          /* (the field the hint is about; focus adds the amber ring, so it is never only a colour) */
dialog textarea { resize: vertical; min-height: 112px; max-height: 240px; }
.count { font: 11.5px var(--mono); color: var(--dim); text-align: right; }
.err { min-height: 22px; margin: 0 0 8px; color: var(--bad); font-size: 13.5px; }
.dactions { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; }
.send { min-height: 40px; background: var(--amber); color: #1a1409; border: 1px solid transparent; border-radius: 10px; padding: 0 18px; font-weight: 500; }          /* (the clear border is what makes it a button in forced colours) */
.send[aria-disabled="true"] { opacity: .7; cursor: default; }              /* (a message is on its way) */
#contactForm .send { min-width: 9.5em; }                              /* ("Sending…" is shorter than "Send message": the link beside it does not move) */
.done { margin: 0 0 18px; font-size: 16px; line-height: 1.55; color: var(--ink); }
.done:focus { outline: none; }                                       /* (focus lands on it so a screen reader says it; it is not a control, so no ring) */
.alt { color: var(--muted); font-size: 14px; }
.fine { margin: 14px 0 0; font-size: 12px; color: var(--dim); }
dialog .hp { position: absolute; width: 1px; height: 1px; min-height: 0; margin: 0; padding: 0; border: 0; overflow: hidden; clip-path: inset(50%); opacity: 0; pointer-events: none; }      /* the honeypot: out of sight and reach (a real pixel: dialog input would make it a full field) */
/* the procedure dialog (pipeline/spdialog.mjs): a conform box's whole stored procedure, in the contact pop-up's frame, wider; the code scrolls sideways inside its own box, never the page */
dialog.sp { width: min(860px, calc(100vw - 32px)); }               /* (wide enough that the longest line of any procedure shows whole on a desktop) */
html:has(dialog.sp[open]) { overflow: hidden; }
.sp .dhead { align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }          /* (a name and Close that do not fit one row (a 320px phone) go on two; the name is never cut) */
.sp .dhead h2 { font: 500 15px/1.35 var(--mono); overflow-wrap: anywhere; }
.sp .spc { margin: 0 0 12px; font: 12.5px/1.5 var(--mono); color: var(--dim); overflow-wrap: anywhere; }
.sp pre.code { margin: 0; font-size: 12.5px; line-height: 1.55; }
.sp .fine { margin-top: 12px; font: 12px/1.5 var(--mono); }
.spx { flex: none; min-height: 36px; padding: 0 14px; font: 12.5px var(--mono); color: var(--muted); background: none; border: 1px solid var(--line2); border-radius: 999px; transition: color .15s, border-color .15s; }
.spx:hover { color: var(--ink); border-color: var(--amber); }
@media (prefers-reduced-motion: reduce) { dialog.sp[open] { animation: none; } }

/* ---------- the tables screen (pipeline/warehouse.mjs): the page slides out to the left and the screen in from the right; under the top bar, which stays ---------- */
html.whopen { overflow: hidden; }                                     /* (the screen scrolls inside itself; the gutter stays, so nothing moves) */
:is(#view, #foot, body > #stage, body > .lanes) { transition: transform .65s cubic-bezier(.65, 0, .35, 1); }
html.whopen :is(#view, #foot, body > #stage, body > .lanes) { transform: translateX(-100%); }
.whpanel { position: fixed; inset: 0; z-index: 40; background: var(--bg); transform: translateX(100%); visibility: hidden; transition: transform .65s cubic-bezier(.65, 0, .35, 1), visibility 0s .65s; }
html.whopen .whpanel { transform: none; visibility: visible; transition: transform .65s cubic-bezier(.65, 0, .35, 1), visibility 0s; }
.whc { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }      /* the pipes and the dots: under the tables (they run in the gaps) */
.whscroll { position: absolute; inset: 0; overflow: auto; overscroll-behavior: contain; }
.whin { position: relative; max-width: 1120px; padding: calc(var(--bar) + 46px) 40px 70px 150px; }
.door { --lit: 1; position: absolute; left: 22px; top: 300px; z-index: 1; width: 48px; height: 48px; display: grid; place-items: center; padding: 0; border: 1px solid var(--line2); border-radius: 14px; background: var(--panel); color: var(--muted); transition: border-color .15s, color .15s, transform .15s; }
.door svg { width: 60%; height: 60%; }
.door:hover, .door:focus-visible { color: var(--ink); border-color: var(--amber); transform: scale(1.04); }
.range { display: flex; width: fit-content; border: 1px solid var(--line2); border-radius: 10px; overflow: hidden; }
.range button { min-height: 30px; border: 0; background: none; padding: 5px 14px; white-space: nowrap; font: 12.5px var(--mono); color: var(--muted); transition: color .15s, background-color .15s; }
.range button:hover { color: var(--ink); }
.range button + button { border-left: 1px solid var(--line2); }
.range button[aria-pressed="true"] { background: rgba(240, 180, 76, .16); color: var(--ink); box-shadow: inset 0 -2px 0 var(--amber); }   /* (the chosen range: lit, and marked in amber as the current page is in the top bar) */
.range button:focus-visible { outline-offset: -3px; }
.whstatus { margin: 12px 0 0; color: var(--muted); font-size: 13.5px; }
.whstatus:empty { margin: 0; }                                        /* (always there, so a screen reader hears it when it speaks) */
/* the three tables are cards; the view is a fourth, across from the middle one, where the pipes merge. Tables keep their table roles (the markup says so): the look is grids */
.whgrid { display: grid; grid-template-columns: minmax(0, 1fr) 300px; column-gap: 96px; row-gap: 20px; align-items: start; margin-top: 22px; }
.ws, .agg { position: relative; z-index: 1; border: 1px solid var(--line2); border-radius: 14px; background: var(--panel); overflow: hidden; }
.ws { --sc: 235, 232, 223; grid-column: 1; box-shadow: inset 3px 0 0 rgba(var(--sc), .7); }
.ws[data-lane="youtube"] { --sc: 255, 77, 106; grid-row: 1; } .ws[data-lane="website"] { --sc: 79, 168, 255; grid-row: 2; } .ws[data-lane="blog"] { --sc: 166, 107, 255; grid-row: 3; }
.agg { grid-column: 2; grid-row: 1 / 4; align-self: start; position: sticky; top: 0; z-index: 2; border-color: rgba(240, 180, 76, .3); }
.ws table, .agg table, .ws :is(thead, tbody, tr), .agg :is(thead, tbody, tr) { display: block; width: 100%; border-collapse: collapse; }
.ws :is(th, td), .agg :is(th, td) { display: block; padding: 0; font-weight: 400; text-align: left; }
thead.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.wsh { display: flex; align-items: center; gap: 10px; padding: 12px 16px; background: rgba(255, 255, 255, .028); border-bottom: 1px solid var(--line2); }
.ico { display: grid; place-items: center; flex: none; width: 34px; height: 22px; color: var(--ink); }
.ico svg { width: 22px; height: 22px; }
.ico svg[viewBox="0 0 36 24"] { width: 34px; height: auto; stroke-width: 1.7; }                 /* (the BAM. mark is wide) */
.wsh b { flex: 1; min-width: 0; font-weight: 500; }
.tname { font: 500 14px var(--mono); letter-spacing: .02em; overflow-wrap: anywhere; }
.kind { font: 10.5px var(--mono); letter-spacing: .09em; text-transform: uppercase; color: var(--dim); border: 1px solid var(--line2); border-radius: 6px; padding: 1px 6px; }
.wsh > .wv { font-size: 15px; }
.wv { font: 13.5px var(--mono); font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
.wg { border-bottom: 1px solid var(--line); }
.wg:has(+ .wis[hidden]):last-of-type, .ws tbody.wis:last-child { border-bottom: 0; }
/* a kind's row: the whole row is its button (stretched over it); the swatch and name, then a bar, the count and a chevron */
tr.wr, tr.wi { position: relative; display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 2fr); align-items: center; column-gap: 12px; }
tr.wr { padding: 9px 16px; font-size: 14px; }
tr.wr:hover { background: rgba(255, 255, 255, .03); }
tr.wr th, tr.wi th { min-width: 0; }
tr.wi .wn { display: block; }                                         /* (a long name ends in an ellipsis inside its column; the whole name is its title and its accessible name) */
tr.wr button { display: flex; align-items: center; gap: 12px; width: 100%; padding: 0; border: 0; background: none; text-align: left; font: inherit; color: inherit; }
tr.wr button::after { content: ""; position: absolute; inset: 0; }    /* (the whole row takes the click) */
tr.wr button:focus-visible { outline: none; }
tr.wr:has(button:focus-visible) { outline: 2px solid var(--amber); outline-offset: -2px; border-radius: 4px; }
.sh { flex: none; width: 8px; height: 8px; border-radius: 50%; }
.wn { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
tr.wr td, tr.wi td { display: grid; grid-template-columns: minmax(40px, 1fr) 76px; align-items: center; column-gap: 12px; padding-right: 26px; }
.chev { position: absolute; right: 16px; top: 50%; margin-top: -.5lh; color: var(--dim); font-size: 11px; transition: transform .2s; }   /* (in the button, at the row's right end) */
tr.wr.open .chev { transform: rotate(90deg); }
tbody.wis { padding: 0 0 8px; background: rgba(255, 255, 255, .018); border-bottom: 1px solid var(--line); }
tr.wi { padding: 6px 16px 6px 36px; font-size: 13px; color: var(--text); }
tr.wi.nil td { display: block; color: var(--dim); }
.wbar { height: 5px; border-radius: 3px; background: rgba(255, 255, 255, .07); overflow: hidden; }
.wbar i { display: block; width: 0; height: 100%; border-radius: 3px; opacity: .8; transition: width .5s ease; }
/* the view: its name, the grand total big, then one row per source with a bar under it */
.agh { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 12px 16px 0; }
.agg tbody.big tr { display: flex; flex-direction: row-reverse; justify-content: flex-end; align-items: baseline; flex-wrap: wrap; gap: 4px 12px; padding: 4px 16px 12px; }
.agg .big .wv { font: 500 34px/1.1 var(--mono); letter-spacing: -.02em; text-align: left; }
.agg .big th { color: var(--muted); font-size: 13px; }
tr.ag { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 6px 10px; padding: 10px 16px; border-top: 1px solid var(--line); font-size: 14px; }
tr.ag th { display: flex; align-items: center; gap: 10px; min-width: 0; }
tr.ag td { display: contents; }
tr.ag .wbar { grid-column: 1 / -1; }
tr.ag .wbar i { background: rgba(150, 146, 134, .9); }
@media (min-width: 900px) and (max-width: 1099px) { .whgrid { grid-template-columns: minmax(0, 1fr) 236px; column-gap: 60px; } }
/* narrower: the view goes on top and sticks under the top bar, compact (its three sources side by side), while the tables scroll under it */
@media (max-width: 899px) {
  .whin { padding: calc(var(--bar) + 16px) 34px 60px 52px; }
  .whgrid { grid-template-columns: minmax(0, 1fr); row-gap: 22px; }
  .agg { grid-row: 1; grid-column: 1; top: var(--bar); }
  .whscroll { scroll-padding-top: var(--stuck, 0px); }   /* (a row focused by Tab or Shift+Tab is scrolled clear of the stuck view, not left under it: WCAG 2.4.11; warehouse.mjs sets --stuck) */
  .agg.stuck { box-shadow: 0 -44px 0 4px var(--bg), 0 12px 26px 4px var(--bg); }   /* (only while it is stuck over tables scrolling under it: the first shadow fills the gap under the top bar, whose foot is see-through, so no row shows there; at rest nothing covers the switch) */
  .ws[data-lane="youtube"] { grid-row: 2; } .ws[data-lane="website"] { grid-row: 3; } .ws[data-lane="blog"] { grid-row: 4; }
  .door { left: 4px; width: 32px; height: 32px; border-radius: 9px; }
  .agh { padding: 10px 14px 0; }
  .agg tbody.big tr { padding: 2px 14px 8px; }
  .agg .big .wv { font-size: 26px; }
  .agg tbody.srcs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border-top: 1px solid var(--line); }
  tr.ag { display: flex; align-items: center; justify-content: center; gap: 8px; padding: 9px 8px; border-top: 0; }
  tr.ag + tr.ag { border-left: 1px solid var(--line); }
  tr.ag .wn { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }   /* (the icon says which: the name stays for a screen reader) */
  tr.ag .ico { width: 26px; height: 18px; } tr.ag .ico svg { width: 18px; height: 18px; } tr.ag .ico svg[viewBox="0 0 36 24"] { width: 26px; }
  tr.ag .wv { font-size: 15px; }
  tr.ag .wbar { display: none; }
}
@media (max-width: 520px) {
  tr.wr td, tr.wi td { grid-template-columns: minmax(0, 1fr); }
  tr.wr .wbar, tr.wi .wbar { display: none; }
  tr.wr, tr.wi { grid-template-columns: minmax(0, 1fr) auto; }
  tr.wr td { min-width: 84px; }
  tr.wr { min-height: 44px; }
  .range button { min-height: 44px; padding: 5px 10px; font-size: 12px; }
  .whin { padding-left: 44px; padding-right: 26px; }
  .door { left: 2px; }
  .wsh { gap: 8px; padding: 12px; }
  .wsh .kind { display: none; }
  .tname { font-size: 12.5px; letter-spacing: 0; }
}
@media (max-width: 360px) { .tname { font-size: 11.5px; } .wsh .ico { width: 24px; } .wsh .ico svg[viewBox="0 0 36 24"] { width: 24px; } tr.wr { padding: 9px 12px; } }

/* ---------- 940px and under (lanes.mjs STRIP_MAX; a unit test keeps the two equal): the page margins cannot hold the lane icons clear of the content, so the pipeline is a strip above the footer, under the content ---------- */
@media (max-width: 940px) {
  #foot { border-top: 1px solid var(--line); }
  #foot .strip { display: block; position: relative; height: 196px; margin: 8px 16px 0; }
  .src::after { content: ""; position: absolute; left: 50%; top: 50%; width: 44px; height: 44px; transform: translate(-50%, -50%); }   /* a 44px place to tap */
}

/* ---------- phones: the logo and the controls on the first row of the top bar, Projects / Writing on the second ---------- */
@media (max-width: 640px) {
  :root { --bar: 104px; }
  #top { flex-wrap: wrap; align-content: flex-start; padding: 8px 18px 0 16px; gap: 0 12px; }
  #topnav { flex-basis: 100%; margin-left: 2px; }
  #view { padding: 112px 16px 48px; }
  .home :where(.spotlight, .find) .btn, .card .btn, .all, .back, .likebtn, .card .ask .linkish, .wlink { min-height: 44px; }
  /* the small controls keep their look but get a 44px tall place to tap */
  :is(.mini, .info summary, .tag, .focusbtn, .fchip, .focusdlg .fx)::after { content: ""; position: absolute; left: 0; right: 0; top: 50%; height: 44px; transform: translateY(-50%); }
  /* "what's this?": its card spans the screen just under its own toggle (main.mjs sets --whats-top when it opens), so it is never cut off and never covers the toggle */
  .info p { position: fixed; left: 16px; right: 16px; top: var(--whats-top, 56px); width: auto; }
  /* the title row: the title and the glass side by side, 44px tall, the box taking what is left of the row; a tag chip (when there is one) has a row of its own under them from the start,
     so opening the box changes nothing, and its tap area (44px) stays clear of the glass above it */
  .lhead { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: start; gap: 12px 6px; }
  .lhead h1 { line-height: 44px; }
  .finder { min-height: 44px; }
  .sbtn { width: 44px; height: 44px; }
  .finder.open .qbox { width: min(300px, calc(100% - 52px)); height: 44px; }                 /* 44 for the glass and 8 between it and the box */
  .qbox { height: 44px; font-size: 16px; }                                                   /* (16px: a phone does not zoom in on the box) */
  .fchip { grid-column: 1 / -1; justify-self: start; margin-left: 0; max-width: 100%; }
  /* the contact pop-up: 44px tall places to tap, and 16px type in the fields (a phone does not zoom in on them) */
  dialog input, dialog textarea { font-size: 16px; }
  dialog input { min-height: 44px; }
  .x { width: 44px; height: 44px; }
  .spx { min-height: 44px; padding: 0 10px; }
  .sp .dwrap { padding: 16px; }
  .sp .dhead h2 { font-size: 13px; }                                 /* (the longest name, 28 characters, and Close fit one row from 360px up) */
  .send { min-height: 44px; }
  .alt { display: inline-flex; align-items: center; min-height: 44px; }
  .card { padding: 18px 16px; }
  .card.has-video { grid-template-columns: minmax(0, 1fr); }
  .card.has-video .vid { order: -1; }
  .focusdlg .fx { top: 12px; right: 16px; }
  .focusdlg .fcol { width: calc(100% - 32px); padding-top: 76px; }
  .plist li, .plist li > a { grid-template-columns: minmax(0, 1fr) auto; }
  .plist .d { grid-column: 1 / 3; }
  .plist .s, .plist .sn, .plist .tg { grid-column: 1 / 3; }
}

/* ---------- the narrowest phones (under about 362px): the logo, sound, pause and what's this? no longer fit on one row, so the controls wrap to a row of their own and the bar has three rows ---------- */
@media (max-width: 361px) {
  :root { --bar: 122px; }
  #view { padding-top: 130px; }
}
