/* Dirk Weather — a broadcast look that is still a sibling of Clara Ranch:
   Almanac's warm paper and serif numerals in light, the studio's midnight and
   amber in dark. One accent, used sparingly, so an alert can still shout. */

:root{
  --ground:#f3efe6; --surface:#fbf8f1; --surface2:#f7f2e7;
  --line:#e4dbca; --ink:#2b2620; --muted:#8a7f6b; --dim:#a99d87;
  --accent:#b3502e;          /* rust */
  --on-accent:#fff;          /* 5.1:1 on the rust */
  --cool:#3f7f97; --played:#4f6a45; --good:#5f7a53; --warn:#a8842b; --bad:#a8442e;
  --num:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
  --sans:system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --r:7px;
  --ver:#756b58;             /* 4.9:1 on the light header, 4.6:1 on the splash */
  --safe-t:env(safe-area-inset-top,0px);
  --safe-b:env(safe-area-inset-bottom,0px);
  --safe-l:env(safe-area-inset-left,0px);
  --safe-r:env(safe-area-inset-right,0px);
  /* How far iOS smears its status-bar wash BELOW the inset: about 10 CSS px,
     measured on David's iPhone 16 Pro (2026-09-25). min() with the inset
     makes it 0 wherever there is no status bar, so a PC window does not pay
     for a phone's problem. See ios-status-bar-blur-bleed in memory. */
  --notch-bleed:min(14px, env(safe-area-inset-top,0px));
}
:root[data-theme="dark"], :root:not([data-theme="light"]){ }
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --ground:#12141c; --surface:#191d27; --surface2:#1f2431;
    --line:#2c3242; --ink:#f0ece2; --muted:#98a0b0; --dim:#6f7787; --ver:#98a0b0;
    --accent:#e2884a; --cool:#5aa9c9; --played:#6fae7d; --good:#6fae7d; --warn:#d8a13c; --bad:#d05a45;
    --on-accent:#12141c;     /* 6.9:1 on the amber; white there is only 2.7:1 */
  }
}
:root[data-theme="dark"]{
  --ground:#12141c; --surface:#191d27; --surface2:#1f2431;
  --line:#2c3242; --ink:#f0ece2; --muted:#98a0b0; --dim:#6f7787; --ver:#98a0b0;
  --accent:#e2884a; --cool:#5aa9c9; --played:#6fae7d; --good:#6fae7d; --warn:#d8a13c; --bad:#d05a45;
  --on-accent:#12141c;
}

*{margin:0;padding:0;box-sizing:border-box}

/* The version, in the top right corner, over everything including the boot
   splash (z-index 50). Sits inside the top safe inset and above the header's
   own content, which starts ten pixels lower, so it never covers a control.
   Never catches a tap. */
/* THE STATUS-BAR STRIP. iOS 26 lays its Liquid Glass blur over the top of a
   Home Screen web app, bleeding a little below the status bar, wherever it
   cannot find a flat colour at the top edge. It blurred "Dirk Weather" and
   the version label (David, 2026-09-25: "top looks bad"). WebKit skips the
   blur when an OPAQUE FIXED box touches the top edge and extends that box's
   colour up instead, so this is that box, in the header's own colour and
   exactly as tall as the inset. Zero tall anywhere without one.
   Below the boot splash (50) on purpose: while the splash shows, it is the
   box touching the top, in its own colour. */
#statusfill{
  position:fixed; top:0; left:0; right:0; height:var(--safe-t);
  background:var(--surface); z-index:40; pointer-events:none;
}
#appver{
  position:fixed; z-index:60; pointer-events:none;
  /* Just below the bleed on a phone (inset + 12, the smear ends near +10)
     and above the header's controls (which now start at inset + 24). At
     the very top edge it read as a smudge on the iPhone: "top looks bad". */
  top:calc(var(--safe-t) + max(0px, var(--notch-bleed) - 2px));
  right:calc(var(--safe-r) + 8px);
  font:600 9.5px/1 var(--sans); letter-spacing:.04em;
  color:var(--ver); font-variant-numeric:tabular-nums;
}
/* A newer version is live than the one that loaded: say so in the accent,
   which measures 4.8:1 light and 6.3:1 dark. */
#appver.stale{color:var(--accent)}
/* app.js failed to load (the onerror on its script tag). The app never leaves
   the boot splash then, so this sits on --ground: 5.18:1 light, 4.58:1 dark. */
#appver.fail{color:var(--bad);font-weight:700}
/* An author `display:` on any of these would silently beat the hidden attribute,
   which has cost real debugging time before. Make it non-negotiable. */
[hidden]{display:none !important}

html,body{height:100%;overflow:hidden}
body{
  background:var(--ground); color:var(--ink); font-family:var(--sans);
  font-size:15px; line-height:1.45; -webkit-font-smoothing:antialiased;
  overscroll-behavior:none;
}
.num,.hi,.lo{font-family:var(--num);font-variant-numeric:tabular-nums}
.muted{color:var(--muted)}
.err{color:var(--bad)}

/* ── app shell: fixed chrome, one scroll region ──────────────────────── */
/* Pinned to all four edges rather than sized height:100dvh. In a Home
   Screen app with the translucent status bar, 100dvh comes out short by
   the top inset, and on David's iPhone that left a band of bare page about
   60pt tall under the tab bar (2026-09-25). There since the first commit,
   noticed then. A fixed box with inset:0 is sized by the viewport itself. */
#app{
  position:fixed; inset:0;
  display:flex; flex-direction:column; overflow:hidden;
  padding-left:var(--safe-l); padding-right:var(--safe-r);
}
.hdr{
  flex:0 0 auto; display:flex; align-items:center; justify-content:space-between;
  gap:12px; padding:calc(10px + var(--safe-t) + var(--notch-bleed)) 16px 10px;
  border-bottom:1px solid var(--line); background:var(--surface);
}
.brand{display:flex;align-items:center;gap:11px;min-width:0}
.brand b{display:block;font-size:16px;letter-spacing:.06em}
.brand i{display:block;font-style:normal;font-size:12px;color:var(--muted);
  letter-spacing:.10em;text-transform:uppercase}
.mark{width:9px;height:34px;background:var(--accent);border-radius:2px;flex:0 0 auto}
.mark.big{width:14px;height:clamp(34px,6vh,52px);margin:0 auto clamp(6px,1.6vh,14px)}

#main{
  flex:1; min-height:0; overflow-y:auto; overflow-x:hidden;
  overscroll-behavior:contain; -webkit-overflow-scrolling:touch;
}
.tab{max-width:min(97vw,1500px);margin:0 auto;padding:16px 16px 24px;
  min-height:100%;display:flex;flex-direction:column;gap:14px}

.tabbar{
  flex:0 0 auto; display:flex; gap:2px; border-top:1px solid var(--line);
  background:var(--surface); padding-bottom:var(--safe-b);
}
.tabbar button{
  flex:1; min-width:30px; padding:11px 4px; background:none; border:0;
  color:var(--muted); font:inherit; font-size:12px; letter-spacing:.06em;
  cursor:pointer; border-top:2px solid transparent;
}
.tabbar button.on{color:var(--accent);border-top-color:var(--accent)}
/* David's bar carries seven tabs since Notes (2026-09-26), and at iPhone
   width "Explainers" needed 64px of a 52px share. When his tabs are showing on
   a narrow screen, each button takes the room its label needs. Julia's four
   stay evenly spaced. */
@media (max-width:480px){
  .tabbar:has(.dav:not([hidden])) button{flex:1 1 auto;padding:11px 2px;letter-spacing:.02em;font-size:11.5px}
}

/* ── cards ───────────────────────────────────────────────────────────── */
.grid{
  display:grid; gap:14px; align-content:start;
  /* min-content rows: 1fr stretches every short card to the tallest sibling and
     is what caused the overflow it looked like it was solving. */
  grid-auto-rows:min-content;
  grid-template-columns:repeat(auto-fill,minmax(min(300px,100%),1fr));
}
.card{
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r);
  padding:16px; min-width:0;
}
.card.wide{grid-column:1/-1}
.card h3{
  font-size:12px; letter-spacing:.13em; text-transform:uppercase;
  color:var(--muted); font-weight:600; padding-bottom:8px; margin-bottom:12px;
  border-bottom:1px solid var(--line);
}

/* ── the player ──────────────────────────────────────────────────────── */
#playerCard{padding:0;overflow:hidden}
.player{position:relative;background:#0d0f15;aspect-ratio:16/9;width:100%}
.player video{width:100%;height:100%;display:block;object-fit:contain;background:#0d0f15}
.novideo{
  position:absolute;inset:0;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:6px;text-align:center;padding:24px;
  color:#f0ece2;
}
.nv-mark{width:12px;height:44px;background:var(--accent);border-radius:2px;margin-bottom:8px}
.playerbar{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:13px 16px;border-top:1px solid var(--line);flex-wrap:wrap;
}
.ep-title{font-size:16px;font-weight:600}
.ep-sub{font-size:12.5px;letter-spacing:.06em;text-transform:uppercase}

.alertbanner{
  grid-column:1/-1; display:flex; align-items:center; gap:14px;
  background:linear-gradient(90deg,var(--bad),color-mix(in srgb,var(--bad) 65%,var(--ground)));
  color:#fff; border-radius:var(--r); padding:14px 16px; font-size:15px;
}
.alertbanner .tag{
  background:#fff;color:var(--bad);font-weight:800;font-size:11px;letter-spacing:.16em;
  text-transform:uppercase;padding:5px 10px;border-radius:4px;white-space:nowrap;
}

/* ── stat blocks ─────────────────────────────────────────────────────── */
.hero{display:flex;align-items:flex-end;gap:22px;flex-wrap:wrap}
.hero .big{font-size:clamp(56px,13vw,92px);line-height:.9}
.hero .deg::after{content:"°";font-size:.5em;vertical-align:super}
.stats{display:flex;gap:20px;flex-wrap:wrap}
.stat .k{font-size:10.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--muted)}
.stat .v{font-size:24px;font-family:var(--num);font-variant-numeric:tabular-nums}

.days{display:grid;grid-template-columns:repeat(7,1fr);gap:6px}
.day{text-align:center;padding:10px 3px;border-radius:5px;background:var(--surface2);
  position:relative;overflow:hidden;min-width:0}
.day.alert{background:color-mix(in srgb,var(--bad) 16%,var(--surface2))}
.day .flag{position:absolute;top:0;left:0;right:0;height:3px;background:var(--bad)}
.day .d{font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
.day .hi{font-size:20px;margin-top:4px}
.day .lo{font-size:13px;color:var(--muted)}
.day .p{font-size:10.5px;color:var(--cool);margin-top:2px;min-height:14px}

.sugar-line{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.sugar-line .lvl{font-size:30px;font-family:var(--num)}
.chip{
  display:inline-flex;align-items:center;gap:6px;padding:4px 11px;border-radius:999px;
  background:var(--surface2);border:1px solid var(--line);font-size:12.5px;
}

/* ── lists, buttons, forms ───────────────────────────────────────────── */
.list{display:flex;flex-direction:column;gap:8px}
.item{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  padding:12px 14px;display:flex;align-items:center;gap:12px;justify-content:space-between;
  flex-wrap:wrap;cursor:pointer;
}
.item .t{font-weight:600}
.item .s{font-size:12.5px;color:var(--muted)}
a.item{text-decoration:none;color:inherit}
.rotwarn{position:absolute;left:0;right:0;top:0;z-index:2;
  background:#d8a13c;color:#12141c;font-size:11.5px;font-weight:600;
  padding:4px 7px;text-align:center;border-radius:6px 6px 0 0}
#picOffered figure{position:relative}

button{
  font:inherit;font-size:14px;padding:9px 15px;border-radius:5px;border:1px solid transparent;
  background:var(--accent);color:#fff;cursor:pointer;
}
button:disabled{opacity:.55;cursor:progress}
button.ghost{background:none;border-color:var(--line);color:var(--ink)}
/* An anchor dressed as the primary button, for actions that are really
   navigations (the podcast subscribe link). Same metrics as button so the two
   sit level in a row. */
.btn-link{
  display:inline-block;font:inherit;font-size:14px;padding:9px 15px;border-radius:5px;
  border:1px solid transparent;background:var(--accent);color:#fff;text-decoration:none;
  line-height:normal;cursor:pointer;white-space:nowrap;
}
.row-btns{display:flex;gap:8px;flex-wrap:wrap}
.viewhead{display:flex;align-items:center;gap:12px}
.viewhead h2{font-size:15px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);font-weight:600}

.out{
  margin-top:12px;padding:11px 13px;border-radius:5px;background:var(--surface2);
  border:1px solid var(--line);font-size:13.5px;white-space:pre-wrap;
  /* A long log line must scroll inside its own box, never the page. */
  overflow-x:auto;
}
.script{display:flex;flex-direction:column;gap:10px;font-size:14.5px}
.beat{border-left:3px solid var(--line);padding-left:11px}
.beat.oncam{border-left-color:var(--accent)}
.beat .meta{font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--dim)}

input[type=password],input[type=text],textarea{
  font:inherit;padding:9px 11px;border-radius:5px;border:1px solid var(--line);
  background:var(--surface);color:var(--ink);width:100%;max-width:100%;
}

/* ── boot splash ─────────────────────────────────────────────────────── */
#boot{
  position:fixed;inset:0;background:var(--ground);display:flex;
  align-items:center;justify-content:center;z-index:50;
  padding:calc(24px + var(--safe-t)) 24px calc(24px + var(--safe-b));
}
.bootinner{text-align:center;max-width:320px;width:100%}
.bootname{font-size:22px;letter-spacing:.20em;text-transform:uppercase;margin-bottom:clamp(2px,1vh,8px)}
/* PIN keypad (house standard 2026-10-20): on-screen digits, nine dots, submits itself on the last digit, no text field to zoom into. */
.pin-grp{display:flex;flex-direction:column;align-items:center;gap:clamp(8px,1.6vh,16px);
  touch-action:manipulation;-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
.pin-dots{display:flex;gap:10px}
.pin-dots span{width:14px;height:14px;border-radius:50%;border:2px solid var(--ink)}
.pin-dots span.on{background:var(--ink)}
.pin-grp.busy .pin-dots span.on{animation:pinpulse .9s ease-in-out infinite}
@keyframes pinpulse{50%{opacity:.35}}
.pin-grp.bad .pin-dots{animation:pinshake .35s}
@keyframes pinshake{20%,60%{transform:translateX(-8px)}40%,80%{transform:translateX(8px)}}
.pin-msg{min-height:1.3em;font-size:16px;color:var(--ink);text-align:center}
.pin-pad{--k:clamp(56px,min(22vw,9vh),84px);display:grid;grid-template-columns:repeat(3,var(--k));gap:clamp(8px,1.5vh,16px)}
.pin-pad button{height:var(--k);border-radius:50%;border:1px solid var(--line);padding:0;background:var(--surface);color:var(--ink);
  font-family:var(--num);font-weight:600;font-size:clamp(26px,4vh,32px);line-height:1;
  touch-action:manipulation;-webkit-tap-highlight-color:transparent;cursor:pointer}
.pin-pad button:active{background:var(--accent);color:var(--on-accent)}
.pin-pad button:disabled{opacity:.5}
.pin-pad .pin-del{border:none;background:transparent;font-size:24px}
#pinPad .linkish{color:var(--ink);font-size:14px;min-height:36px}
#signIn{margin-top:20px;display:flex;flex-direction:column;gap:9px}
#pinPad{margin-top:clamp(8px,2vh,20px);display:flex;flex-direction:column;align-items:center;gap:6px}
.linkish{background:none;border:0;color:var(--muted);text-decoration:underline;
  font-size:13px;padding:6px;cursor:pointer}

#toast{
  position:fixed;left:50%;transform:translateX(-50%);
  bottom:calc(74px + var(--safe-b));z-index:60;
  background:var(--ink);color:var(--ground);padding:10px 16px;border-radius:6px;
  font-size:14px;max-width:min(92vw,460px);box-shadow:0 6px 22px rgba(0,0,0,.25);
}

@media (max-width:520px){
  .day .hi{font-size:17px}
  .day .cond{display:none}
  .tab{padding:12px 12px 20px}
}

/* ── recording booth ─────────────────────────────────────────────────── */
#rec{
  position:fixed;inset:0;z-index:70;background:rgba(10,12,18,.86);
  display:flex;align-items:center;justify-content:center;
  padding:calc(16px + var(--safe-t)) 16px calc(16px + var(--safe-b));
}
.rec-box{
  position:relative;background:var(--surface);border:1px solid var(--line);
  border-radius:12px;padding:26px 22px;width:min(680px,100%);
  max-height:100%;overflow-y:auto;overflow-x:hidden;text-align:center;
}
.rec-close{
  position:absolute;top:8px;right:8px;background:none;border:0;color:var(--muted);
  font-size:26px;line-height:1;padding:6px 10px;cursor:pointer;
}
.rec-kind{font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--accent)}
.rec-title{font-size:13px;letter-spacing:.10em;text-transform:uppercase;color:var(--muted);margin-top:4px}
.rec-line{
  font-family:var(--num);font-size:clamp(20px,3.4vw,29px);line-height:1.42;
  margin:18px 0 12px;text-align:left;
}
.rec-why{font-size:13px;text-align:left;margin-bottom:18px}
.rec-meter{
  height:10px;border-radius:999px;background:var(--surface2);
  border:1px solid var(--line);overflow:hidden;margin-bottom:8px;
}
.rec-meter i{display:block;height:100%;width:0;background:var(--good);transition:width .06s linear}
.rec-meter i.hot{background:var(--bad)}
.rec-status{font-size:13px;color:var(--muted);min-height:20px;margin-bottom:14px}
.rec-status.live{color:var(--bad);font-weight:600}
.rec-controls{display:flex;gap:8px;justify-content:center;flex-wrap:wrap}
#recPlay{width:100%;margin-top:16px}
.rec-verdict{
  margin-top:14px;padding:10px 12px;border-radius:6px;font-size:13.5px;text-align:left;
  background:var(--surface2);border:1px solid var(--line);
}
.rec-verdict.bad{border-color:var(--bad);color:var(--bad)}
.rec-verdict.good{border-color:var(--good)}
.take{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;justify-content:space-between;
  padding:8px 10px;border:1px solid var(--line);border-radius:6px;background:var(--surface2);
}
.take .meta{font-size:12.5px;color:var(--muted)}
.tag-on{background:var(--accent);color:#fff;border-color:var(--accent)}

/* ── filmed takes (Voice tab) ─────────────────────────────────────────── */
.vh{position:absolute;width:1px;height:1px;opacity:0;overflow:hidden;pointer-events:none}
.takes-form{display:flex;gap:12px;flex-wrap:wrap;align-items:flex-end;margin-top:12px}
.takes-form .fld{display:flex;flex-direction:column;gap:5px;font-size:12.5px;color:var(--muted);flex:1 1 260px;min-width:0}
.takes-form select{font:inherit;font-size:15px;padding:9px 10px;border-radius:5px;border:1px solid var(--line);
  background:var(--surface);color:var(--ink);max-width:100%}
.take-pick{position:relative;font-size:15px;padding:11px 18px}
.take-row{cursor:default}
.take-row .t{overflow-wrap:anywhere}
.take-bar{height:6px;border-radius:3px;background:var(--surface2);overflow:hidden;flex:1 1 100%}
.take-bar i{display:block;height:100%;width:0;background:var(--accent);transition:width .2s}
.take-st{font-size:12.5px;padding:3px 8px;border-radius:10px;border:1px solid var(--line);white-space:nowrap}
.take-st.ok{color:var(--good);border-color:var(--good)}
.take-st.bad{color:var(--warn);border-color:var(--warn)}
.take-retry{display:flex;gap:8px;flex-wrap:wrap;flex:1 1 100%}
.take-retry select{font:inherit;font-size:14px;padding:7px 8px;border-radius:5px;border:1px solid var(--line);
  background:var(--surface);color:var(--ink);min-width:0;max-width:100%;flex:1 1 200px}
.take-lines{margin-top:14px}
.take-lines summary{cursor:pointer;font-weight:600}
.take-lines ol{margin:10px 0 0 22px;display:flex;flex-direction:column;gap:6px;font-size:16px;line-height:1.35}
.take-pick.busy{opacity:.6;pointer-events:none}

/* Uploaded photographs. Small enough to see a dozen at once, big enough to
   tell a sunset from a storm, which is the only judgement being made here. */
.photo-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px}
.photo-grid figure{margin:0;border-radius:10px;overflow:hidden;
  background:var(--panel2,#1d2230);border:1px solid var(--line,#2b3243)}
.photo-grid img{display:block;width:100%;height:100px;object-fit:cover}
.photo-grid figcaption{display:flex;align-items:center;justify-content:space-between;
  gap:6px;padding:6px 8px;font-size:13px;color:var(--muted,#9aa3b5)}
.photo-grid .rm{border:0;background:none;color:var(--bad,#d05a45);cursor:pointer;
  font-size:13px;padding:2px 4px}

/* The decide buttons inside a picture card.
   `button.ghost` sets colour to --ink and `.photo-grid figcaption` sets it to
   --muted. Both are one class plus one element, so they have the SAME
   specificity, and equal specificity resolves by source order: figcaption is
   further down this file and won. The buttons came out grey on grey and were
   unreadable. These selectors are more specific than either, so the question
   does not arise again. */
.photo-grid figcaption button{font-size:13px;padding:5px 12px;border-radius:6px;
  border:1px solid var(--line);cursor:pointer;font-weight:600}
.photo-grid figcaption button.use{color:#fff;background:var(--good);
  border-color:var(--good)}
.photo-grid figcaption button.rej{color:var(--bad);background:none;
  border-color:var(--bad)}
/* Dark mode needs different ink, not the same ink on a darker ground.
   --good there is a LIGHT green meant for text, so white on it measures 2.62
   and fails outright; dark ink on the same fill measures 7.03. And --bad at
   4.20 is under the 4.5 these 13px labels need, so this one lifts it. Both
   measured rather than eyeballed. */
@media (prefers-color-scheme: dark) {
  .photo-grid figcaption button.use{color:#12141c}
  .photo-grid figcaption button.rej{color:#e8755f;border-color:#e8755f}
}
.photo-grid figcaption button:disabled{opacity:.55;cursor:default}
.photo-grid figcaption .rm{color:var(--bad);font-weight:600}

/* ── Notes: every Dirk's Note, newest first (2026-09-26) ─────────────────
   A card per note: title, when it aired, the opening sentences so the right
   one can be found by eye, then Play (inline, right under the words) and
   Share. Share is the primary action, so it takes the accent; its text is
   --on-accent, never plain white (white on the dark amber is 2.7:1). */
.notes .note{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  padding:13px 15px;display:flex;flex-direction:column;gap:8px;min-width:0;
}
.notes .note .t{font-weight:650;font-size:16px;line-height:1.25}
.notes .note .s{font-size:12.5px;color:var(--ver)}   /* --muted is 3.7:1 on the light card; --ver is 4.9 light, 6.4 dark */
.notes .note .term{color:var(--accent);font-weight:600}
.notes .note .nx{font-size:14px;line-height:1.5;color:var(--ink);overflow-wrap:anywhere}
.notes .note .nact{display:flex;gap:8px;flex-wrap:wrap}
/* David's view: what Julia has done with this note. Muted until she has
   played it; then the accent-ink green, so a scan of the list finds them. */
.notes .note .njulia{font-size:12.5px;color:var(--ver);margin:2px 0 6px}
.notes .note .njulia.on{color:var(--played);font-weight:600}   /* 5.69:1 light, 6.44:1 dark on --surface */
.notes .note button.nplay{background:none;border:1px solid var(--line);color:var(--ink)}
.notes .note button.nshare{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
.notes .note button.nshare.wait{background:none;border-color:var(--line);color:var(--ver)}
.notes .note .nvid video{display:block;width:100%;max-width:720px;aspect-ratio:16/9;
  background:#000;border-radius:6px}
@media (min-width:900px){
  .notes{display:grid;grid-template-columns:repeat(auto-fill,minmax(380px,1fr));gap:12px}
}

/* Notes: search and stars (2026-09-26). The search box is 16px so iOS does
   not zoom the page when it takes focus. Highlights are measured:
   ink on #f6e3a6 is 11.8:1 in light, #f0ece2 on #5a4a1c is 7.2:1 in dark. */
.notebar{display:flex;gap:8px;align-items:stretch;flex-wrap:wrap}
.nsearch{position:relative;flex:1 1 220px;min-width:0}
.nsearch input{width:100%;font:inherit;font-size:16px;padding:10px 40px 10px 12px;
  border:1px solid var(--line);border-radius:var(--r);background:var(--surface);color:var(--ink)}
.nsearch input::placeholder{color:var(--ver)}
.nsearch .nclear{position:absolute;right:4px;top:50%;transform:translateY(-50%);
  width:36px;height:36px;padding:0;font-size:22px;line-height:1;background:none;border:0;color:var(--ver)}
button.nstarf{background:none;border:1px solid var(--line);color:var(--ink);white-space:nowrap}
button.nstarf[aria-pressed="true"]{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
.ncount{font-size:12.5px;color:var(--ver);min-height:1em}
.notes .note .nhead{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}
.notes .note button.nstar{flex:0 0 auto;width:44px;height:44px;margin:-8px -8px 0 0;padding:0;
  background:none;border:0;font-size:24px;line-height:1;color:var(--ver)}
.notes .note button.nstar.on{color:var(--accent)}
.notes .note .nsnip{font-size:13.5px;line-height:1.5;color:var(--ink);border-left:3px solid var(--line);
  padding-left:10px;font-style:italic;overflow-wrap:anywhere}
.notes mark{background:#f6e3a6;color:#2b2620;border-radius:3px;padding:0 1px}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]) .notes mark{background:#5a4a1c;color:#f0ece2}
}
:root[data-theme="dark"] .notes mark{background:#5a4a1c;color:#f0ece2}
.nempty{padding:18px 4px}

/* Notes: categories (2026-09-26). On a phone the buttons are one row that
   scrolls sideways INSIDE itself (the page never does); from tablet width
   they wrap. Selected is the accent with --on-accent (5.1 light, 6.9 dark);
   the counts are --ver on the surface (4.9 light, 6.4 dark). */
.ncats{display:flex;gap:6px;overflow-x:auto;overscroll-behavior-x:contain;
  scrollbar-width:none;-webkit-overflow-scrolling:touch;padding:1px 0 3px;min-width:0}
.ncats::-webkit-scrollbar{display:none}
.ncats:empty{display:none}
@media (min-width:768px){ .ncats{flex-wrap:wrap;overflow:visible} }
.ncats button.ncat{flex:0 0 auto;font-size:13.5px;padding:8px 13px;border-radius:999px;
  background:var(--surface);border:1px solid var(--line);color:var(--ink);white-space:nowrap}
.ncats button.ncat .nc{color:var(--ver);font-size:12px;margin-left:3px}
.ncats button.ncat[aria-pressed="true"]{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
.ncats button.ncat[aria-pressed="true"] .nc{color:var(--on-accent)}
.notes .note .ntags{display:flex;gap:6px;flex-wrap:wrap}
.notes .note button.ntag{font-size:12.5px;padding:5px 10px;border-radius:999px;
  background:var(--surface2);border:1px solid var(--line);color:var(--ink)}

/* Notes and Explainers: the picture on each card (2026-09-26). Cut from the
   note's own slide (src/noteicons.ts): a plate or photograph fills its square;
   a drawing is shown whole on the broadcast's own dark ground, which is what
   it was drawn on. The placeholder knight is --ver on --surface2 (4.7:1 light, 6.1:1 dark). */
.notes .note .nhead{align-items:center}
.notes .note .nhtext{flex:1 1 auto;min-width:0}
.notes .note button.nart{flex:0 0 auto;width:96px;height:60px;padding:0;border-radius:9px;overflow:hidden;
  border:1px solid var(--line);background:var(--surface2);color:var(--ver);font-size:28px;line-height:1;
  display:flex;align-items:center;justify-content:center;cursor:pointer}
/* Landscape, because the plates are 16:9 and a trimmed drawing is wider than
   tall. Both fill the tile; a drawing too wide for it shows its middle. */
.notes .note button.nart img{width:100%;height:100%;display:block;object-fit:cover;object-position:center}
.notes .note button.nart.diagram{background:#151a26;border-color:#2c3242}
@media (min-width:768px){ .notes .note button.nart{width:128px;height:80px} }
.list .xitem{justify-content:flex-start;flex-wrap:nowrap}
.list .xitem .xart{flex:0 0 auto;width:84px;height:56px;object-fit:cover;border-radius:8px;border:1px solid var(--line)}
.list .xitem .xtext{flex:1 1 auto;min-width:0}
