/* layout.css — panes, header, slide-over, footer.
   Panes: the Active notes, paged by a native sideways scroll; as many side by side as
   fit (panes.js --vis). */

/* GUIDE §2.3 — pinned to the layout viewport, so no height:100% chain has to
   resolve and no viewport unit can disagree with the box it sizes. */
#app { position: fixed; inset: 0; display: flex; flex-direction: column; }

/* ---------- panes ----------
   The Active notes (Gianni, 2026-10-19). panes.js sets --vis, how many fit side by
   side: one on a phone, more where each can be at least 380px wide. The scroller pages
   between them natively; nothing sits over the page to catch a swipe. */

#panes {
  position: relative;
  flex: 1;
  min-height: 0;
  /* GUIDE §3.5 — give back exactly what the bar moved up by, so the text being
     edited is never behind the keyboard. */
  margin-bottom: var(--kb, 0px);
  display: flex;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
}
#panes::-webkit-scrollbar { display: none; }

.pane {
  position: relative;
  flex: 0 0 calc(100% / var(--vis, 1));
  min-width: 0;
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  background: var(--paper);
}
.pane + .pane { border-left: 1px solid var(--rule); }

/* ---------- the one header ----------
   Height is summed explicitly from its parts, exactly like --bar-h, so anything that
   needs to centre on the visible pane area can subtract it instead of measuring —
   and so the top inset is ADDED to the bar rather than padded out of a fixed height
   (GUIDE §3.4). It lived in two places when each pane had its own header; a value
   that has to agree in two places is a value that eventually does not. */
#topbar {
  flex: 0 0 auto;
  box-sizing: border-box;
  height: var(--top-h);
  display: flex;
  align-items: center;
  gap: 6px;
  padding: var(--top-pad) 8px var(--top-pad);
  padding-top: calc(var(--sa-top) + var(--top-pad));
  padding-left: calc(var(--sa-left) + 8px);
  padding-right: calc(var(--sa-right) + 8px);
  border-bottom: var(--top-border) solid var(--rule);
  background: var(--paper);
  user-select: none;
  -webkit-user-select: none;
}
#topbar > button[data-act] {
  flex: 0 0 auto;
  width: var(--tap); height: var(--top-row);
  display: grid; place-items: center;
  border-radius: 8px; color: var(--ink-2);
}
#topbar > button[data-act]:hover { background: var(--chrome); color: var(--ink); }

/* The Active notes' tabs. They share the strip and shorten their titles rather than
   scroll, which also keeps a drag on them a drag (touch-action none) on touch. */
#tabs { flex: 1 1 auto; min-width: 0; display: flex; gap: 3px; touch-action: none; }
.tab {
  flex: 1 1 0;
  min-width: 34px;
  max-width: 220px;
  height: var(--top-row);
  padding: 0 8px;
  text-align: left;
  font-size: 14px; font-weight: 600;
  color: var(--ink-3);
  border-radius: 8px;
  transition: background var(--dur) var(--ease-smoother), color var(--dur) var(--ease-smoother);
}
.tab .tt { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tab:hover { background: var(--chrome); }
/* Current means "the one New Note lands in and the footer acts on". */
.tab[aria-current="true"] { background: var(--chrome); color: var(--ink); }
.tab[aria-expanded="true"] { box-shadow: inset 0 -2px 0 var(--accent); }
.tab.dragging { opacity: .8; box-shadow: 0 0 0 2px var(--accent); cursor: grabbing; }

/* The second header row: the current note's arrange controls. */
#tabrow {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 4px;
  padding: 4px calc(var(--sa-right) + 8px) 5px calc(var(--sa-left) + 8px);
  border-bottom: 1px solid var(--rule);
  background: var(--paper);
}
#tabrow[hidden] { display: none; }
.trlabel { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
           font-size: 13px; color: var(--ink-2); }
.trbtn {
  flex: 0 0 auto;
  min-width: 40px; height: 40px;
  display: grid; place-items: center;
  border-radius: 8px;
  border: 1px solid var(--rule);
  background: var(--paper);
  color: var(--ink-2);
  font-size: 15px;
}
.trbtn:hover { color: var(--ink); background: var(--chrome); }
.trbtn:disabled { opacity: .35; }

/* The page pans sideways from anywhere, text included: on iOS a plain drag never
   selects (that takes a long press), so the platform can arbitrate by direction. */
.editor {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 14px 16px 28px 14px;     /* the marker gutter lives in .doc (editor.css --gut) */
  touch-action: pan-x pan-y;      /* the page swipes between notes from anywhere */
}

/* ---------- desktop ---------- */

@media (min-width: 480px) {
  .fbtn, .fgbtn { min-width: var(--tap); }
}

/* ---------- slide-over list ---------- */

#scrim {
  position: fixed; inset: 0; z-index: 20;
  background: rgba(0,0,0,.34);
}

#sidebar {
  position: fixed;
  z-index: 21;
  top: 0; left: 0; bottom: 0;
  padding-left: var(--sa-left);
  width: min(86vw, 340px);
  display: flex;
  flex-direction: column;
  background: var(--paper-2);
  border-right: 1px solid var(--rule);
  box-shadow: 0 0 40px rgba(0,0,0,.18);
  transform: translateX(-100%);
  transition: transform var(--dur) var(--ease-smoother);
}
#sidebar.open { transform: none; }
@media (prefers-reduced-motion: reduce) { #sidebar { transition: none; } }

.sb-hd { padding: calc(var(--sa-top) + 12px) 14px 8px; border-bottom: 1px solid var(--rule); }
.sb-hd .row1 { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.sb-hd h1 { flex: 1; margin: 0; font-size: 20px; font-weight: 700; letter-spacing: -.01em; }
.sb-hd button.icon {
  width: var(--tap); height: var(--tap);
  display: grid; place-items: center;
  border-radius: 8px; color: var(--accent-ink);
}
.sb-hd button.icon:hover { background: var(--chrome); }

#folders { display: flex; gap: 6px; overflow-x: auto; padding: 0 14px; margin: 10px 0 0; scrollbar-width: none; }
#folders::-webkit-scrollbar { display: none; }
#folders button {
  flex: 0 0 auto;
  padding: 5px 11px;
  border-radius: 999px;
  font-size: 13px;
  color: var(--ink-2);
  background: var(--chrome);
  white-space: nowrap;
}
#folders button[aria-pressed="true"] { background: var(--accent); color: var(--on-accent); }

#list { flex: 1; overflow-y: auto; padding: 8px 10px 24px; }
.sb-ft { display:flex; flex-wrap:wrap; gap:6px 12px; align-items:center;
         padding: 10px 14px calc(var(--sa-bottom) + 14px); border-top:1px solid var(--rule); }
.quiet { font-size:13px; color:var(--ink-3); }
.quiet:hover { color: var(--ink-2); }
/* the list's bottom row: phone-sized targets, readable on --paper-2 */
.sb-ft .quiet { min-height: 44px; padding: 0 4px; color: var(--ink-2); }
/* A row carries its own destinations. pan-y is what makes the swipe possible without
   a gesture arbiter: the browser keeps vertical scrolling of the list, and hands us
   anything horizontal. Same split as .editor (pan-y) against the edge strips (pan-x). */
.nrow {
  position: relative;
  display: flex; align-items: center; gap: 4px;
  width: 100%;
  margin-bottom: 2px;
  border-radius: var(--r);
  touch-action: pan-y;
}
.nrow:hover { background: var(--chrome); }
.nrow[aria-current="true"] { background: var(--accent); }
.nrow[aria-current="true"] .t, .nrow[aria-current="true"] .s { color: var(--on-accent); }

.nmain {
  flex: 1 1 auto; min-width: 0;
  display: block; text-align: left;
  padding: 10px 4px 10px 12px;
  border-radius: var(--r);
}
.nrow .t { display: block; font-weight: 600; font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nrow .s { display: block; font-size: 13px; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 1px; }
.nrow .pin { color: var(--accent-ink); }

.nacts { flex: 0 0 auto; display: flex; gap: 2px; padding-right: 6px; }
.nsend {
  width: 30px; height: 34px;
  display: grid; place-items: center;
  border-radius: 7px;
  font-size: 15px; line-height: 1;
  color: var(--ink-3);
}
.nsend:hover { background: var(--paper-2); color: var(--ink); }
.nrow[aria-current="true"] .nsend { color: var(--on-accent); }

/* While a row is being dragged it must paint above its neighbours, or the translate
   slides under the next row instead of over it. */
.nrow.swiping { z-index: 2; }
.nrow.to-left  { background: var(--chrome); box-shadow: inset 3px 0 0 var(--accent); }
.nrow.to-right { background: var(--chrome); box-shadow: inset -3px 0 0 var(--accent); }

#dest { font-size: 12px; color: var(--ink-3); padding: 0 14px; margin: 8px 0 0; }

.empty { padding: 28px 16px; text-align: center; color: var(--ink-3); font-size: 14px; }

/* ---------- footer: two rows of little buttons ---------- */

/* GUIDE §3.4 — the bar's height is content + pad + reserve + BORDER, summed
   explicitly. Under border-box the declared height IS the border box, so padding and
   border come out of the content box: height:60px + padding-bottom:34px leaves ~26px
   of usable bar. The inset is extra chrome the device is demanding, not space the bar
   already had, so it is ADDED. Forgetting the 1px border takes that pixel out of the
   content box and the buttons overflow by exactly one.

   --bar-keep ships at 0px. The claim that the bottom ~15px loses taps to the system
   swipe recogniser is asserted in the source document and explicitly never measured;
   34px of the scarcest axis is not spent on folklore. Raise to 8-12px only if real
   device testing shows dropped taps.

   GUIDE §3.5 — the keyboard shrinks the visual viewport, not the layout viewport, so
   without this transform a fixed bar sits behind the keyboard. */
/* ---------- motion ----------
   ONE duration and ONE curve for everything. Smootherstep (6t^5 - 15t^4 + 10t^3) is
   zero-velocity AND zero-acceleration at both ends, which is what stops a 150ms move
   reading as a snap. CSS cannot evaluate the polynomial, so it is sampled; the JS in
   ui/motion.js evaluates the real thing, and the two are asserted equal in the tests
   so they can never drift.
   The cubic-bezier is the fallback: a browser without linear() keeps the earlier
   declaration, which is why this is two rules and not one with a fallback value —
   a custom property accepts any garbage at parse time and only fails at use time. */
:root {
  --dur: 150ms;
  --ease-smoother: cubic-bezier(.65, 0, .35, 1);
}
@supports (transition-timing-function: linear(0, 1)) {
  :root {
    --ease-smoother: linear(0, 0.0022, 0.0161, 0.0488, 0.1035, 0.18, 0.2752, 0.384,
                            0.5, 0.616, 0.7248, 0.82, 0.8965, 0.9512, 0.9839, 0.9978, 1);
  }
}
/* One place to disable every animation at once, rather than a per-rule override that
   the next transition forgets to add. */
@media (prefers-reduced-motion: reduce) { :root { --dur: 0ms; } }

:root {
  --top-row: 30px;
  --top-pad: 6px;
  --top-border: 1px;
  --top-h: calc(var(--top-row) + var(--top-pad) * 2 + var(--sa-top) + var(--top-border));

  --bar-row: 36px;              /* 2026-10-19: bigger, evenly spread buttons */
  --bar-gap: 3px;
  --bar-pad-top: 5px;
  --bar-keep: 0px;
  --bar-border: 1px;
  --bar-h: calc(var(--bar-row) * 2 + var(--bar-gap) + var(--bar-pad-top) * 2
              + var(--bar-keep) + var(--sa-bottom) + var(--bar-border));
}

#footer {
  flex: 0 0 auto;
  box-sizing: border-box;
  height: var(--bar-h);
  background: var(--chrome);
  border-top: var(--bar-border) solid var(--rule);
  padding: var(--bar-pad-top) 6px calc(var(--bar-keep) + var(--sa-bottom));
  user-select: none;
  -webkit-user-select: none;
  transform: translateY(calc(-1 * var(--kb, 0px)));
  transition: transform var(--dur) var(--ease-smoother);
}
@media (prefers-reduced-motion: reduce) { #footer { transition: none; } }
/* A row never scrolls (Gianni, 2026-10-19). What does not fit is folded into group
   buttons by footer.js, so overflow is hidden, never scrolled. */
.frow {
  display: flex;
  gap: 3px;
  overflow: hidden;
}
.frow + .frow { margin-top: 3px; }
.fgroup { flex: 0 1 auto; display: flex; gap: 3px; min-width: 0; }
.fgroup > .fgbtn { display: none; }      /* 0,2,0: beats the shared .fbtn, .fgbtn rule below */
.fgbtn { position: relative; }
.fgroup.folded > .fbtn { display: none; }
.fgroup.folded > .fgbtn { display: grid; }
/* an open layer takes the row's place: its group's commands and the button that closes it */
/* An open group shows its commands in the OTHER row (Gianni, 2026-10-19: "opening up
   into the opposite row of the button you clicked"). footer.js moves them into that
   row's .flayer; the row's own buttons step aside until it closes. */
.flayer { display: none; }
.frow.layer > :not(.flayer) { display: none; }
.frow.layer > .flayer { display: flex; gap: 3px; flex: 0 1 auto; min-width: 0; }
.flayer > .fbtn { display: grid; }
.fbtn.hot { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
#footer { touch-action: none; }          /* a hold-and-slide is a gesture of its own */
.fgbtn[aria-expanded="true"] { border-color: var(--accent); color: var(--accent-ink); }
.fgbtn.on:not([aria-expanded="true"]) { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.fgbtn .fgi { display: grid; place-items: center; }
/* how many commands the button holds: present, never loud */
.fgbtn .fgn { position: absolute; top: 1px; right: 2px; font: 600 8px/1 var(--font); opacity: .7; }

/* Buttons are a comfortable 52px and shrink together to fill a narrow row (a phone)
   rather than scroll; footer.js folds groups before they would get too narrow. */
.fbtn, .fgbtn {
  flex: 0 1 auto;
  width: 52px;              /* an explicit width: groups size from it (a flex-basis is ignored there) */
  min-width: 32px;
  height: var(--bar-row);
  padding: 0 4px;
  display: grid;
  place-items: center;
  border-radius: 7px;
  font-size: 13px;
  color: var(--ink-2);
  background: var(--paper);
  border: 1px solid var(--rule);
}
.fbtn:hover, .fgbtn:hover { color: var(--ink); }
.fbtn[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.fbtn svg, .fgbtn svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.fsep { flex: 0 0 auto; width: 1px; margin: 3px 3px; background: var(--rule); }

/* ---------- auth gate ---------- */

/* GUIDE §6.3 — the gate is an OVERLAY in the same document, never a redirect. On iOS
   a standalone install has its own storage container and its scope is a navigation
   boundary: crossing it hands the window to the browser, and anything written there
   lands in a container this app will never read. */
#gate {
  position: fixed; inset: 0; z-index: 40;
  display: grid;
  align-items: center; align-items: safe center;   /* GUIDE §3.3 — both, in this order */
  justify-items: center;
  padding: calc(var(--sa-top) + 24px) calc(var(--sa-right) + 24px)
           calc(var(--sa-bottom) + 24px) calc(var(--sa-left) + 24px);
  background: var(--paper);
  overflow-y: auto;
}
.code-in { text-align:center; letter-spacing:.32em; font-size:max(20px,1.25rem); }

/* GUIDE §7.7 — passive, non-modal. Allowed to appear while busy; only the
   interrupting toast is suppressed, so an update is never invisible. */
#updbadge {
  position: fixed; z-index: 30;
  left: 50%; transform: translateX(-50%);
  bottom: calc(var(--bar-h) + var(--kb, 0px) + 10px);
  padding: 7px 14px; border-radius: 999px;
  background: var(--accent); color: var(--on-accent);
  font-size: 13px; font-weight: 600;
  box-shadow: 0 2px 12px rgba(0,0,0,.18);
}

/* The full-screen panels (diag, backups, import, merge, Claude). Fixed and inset-padded rather than in normal flow: the
   sidebar and footer are fixed, so a panel left in flow renders BEHIND them and its
   buttons are unreachable — visible, and not clickable. */
#diag, #backups-panel, #import-panel, #merge-panel, #claude-panel, #train-panel {
  position: fixed; inset: 0; z-index: 50;
  background: var(--paper); overflow-y: auto;
  padding: calc(var(--sa-top) + 14px) calc(var(--sa-right) + 14px)
           calc(var(--sa-bottom) + 14px) calc(var(--sa-left) + 14px);
}
#gate .card { width: min(100%, 340px); text-align: center; }
#gate h1 { font-size: 26px; margin: 0 0 6px; letter-spacing: -.02em; }
#gate p { color: var(--ink-2); font-size: 14px; margin: 0 0 18px; }
#gate form { display: flex; flex-direction: column; gap: 10px; }
.go {
  background: var(--accent); color: var(--on-accent); font-weight: 600;
  padding: 11px; border-radius: var(--r);
}
.go:disabled { opacity: .45; cursor: default; }
#gate .msg { font-size: 13px; margin-top: 12px; min-height: 18px; color: var(--ink-2); }
#gate .msg.bad { color: var(--danger); }

/* ---------- sync pip ---------- */

#pip {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--ink-3);
  transition: background var(--dur) var(--ease-smoother);
}
#pip[data-s="dirty"] { background: var(--accent); }
#pip[data-s="off"]   { background: var(--danger); }
#pip[data-s="ok"]    { background: transparent; }

/* ---------- tooltip ----------
   Own element, not the native `title`: the native delay is the browser's and is about
   a second, and "instantly start displaying" is the requirement. Positioned by
   transform so showing one never triggers layout of anything else. */
#tip {
  position: fixed; top: 0; left: 0; z-index: 90;
  pointer-events: none;
  max-width: 60vw;
  padding: 5px 8px;
  border-radius: 6px;
  background: var(--ink); color: var(--paper);
  font-size: 12px; line-height: 1.25; white-space: nowrap;
  opacity: 0;
  transition: opacity var(--dur) var(--ease-smoother);
}
#tip.on { opacity: .96; }

/* ---------- selection menu ----------
   Triggered by there BEING a selection, not by right-click. On iOS the system callout
   appears too, so this is offset clear of it rather than replacing it — it supplements
   (the 2026-09-17 ruling). */
#selmenu {
  position: fixed; top: 0; left: 0; z-index: 15;
  max-width: min(94vw, 520px);
  border-radius: 10px;
  background: var(--chrome);
  border: 1px solid var(--rule);
  box-shadow: 0 6px 20px rgba(0,0,0,.18);
  opacity: 0;
  transition: opacity var(--dur) var(--ease-smoother);
}
#selmenu.on { opacity: 1; }
.selbar {
  display: flex; align-items: center; gap: 2px;
  padding: 5px 6px;
  overflow-x: auto;
  scrollbar-width: none;
  max-width: min(94vw, 520px);
}
.selbar::-webkit-scrollbar { display: none; }
.selbtn {
  flex: 0 0 auto;
  min-width: 32px; height: 32px;
  display: grid; place-items: center;
  border-radius: 7px;
  color: var(--ink-2);
}
.selbtn:hover { background: var(--paper-2); color: var(--ink); }
.selbtn[aria-pressed="true"] { background: var(--accent); color: var(--on-accent); }
.selbtn svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

/* ---------- unfinished ----------
   Operator's rule: a command that does not have all three surfaces plus a working
   implementation must LOOK unfinished, in the app, without anyone running a test. */
.fbtn.incomplete, .selbtn.incomplete {
  box-shadow: inset 0 0 0 2px var(--danger);
  position: relative;
}
.fbtn.incomplete::after, .selbtn.incomplete::after {
  content: "";
  position: absolute; top: 2px; right: 2px;
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--danger);
}

/* ---------- Merge and Claude panels ---------- */

.mg-l { display:block; font-size:13px; margin:10px 0 4px; }
.mg-in { width:100%; box-sizing:border-box; padding:8px 10px; border-radius:8px; border:1px solid var(--rule);
         background:var(--paper); color:var(--ink); font-size:16px; }
.cl-chip { font-size:13px; padding:6px 10px; border-radius:999px; border:1px solid var(--rule);
           background:var(--chrome); color:var(--ink); min-height:32px; max-width:100%;
           overflow:hidden; text-overflow:ellipsis; white-space:nowrap; display:inline-flex; align-items:center; }
.cl-ct { min-width:0; overflow:hidden; text-overflow:ellipsis; }
select.cl-chip { font-size: max(16px, 1rem); }   /* under 16px, iOS zooms the page on focus */
.cl-row { padding:10px 0; border-top:1px solid var(--rule); }
.cl-meta { font-size:12px; color:var(--ink-3); margin-bottom:4px; }
.cl-st { font-weight:600; color:var(--ink-2); }
.cl-st[data-s="done"] { color:var(--accent-ink); }
.cl-q { font-size:14px; white-space:pre-wrap; overflow-wrap:anywhere; }
.cl-a { font-size:14px; white-space:pre-wrap; overflow-wrap:anywhere; margin-top:6px; padding:8px 10px;
        border-radius:8px; background:var(--chrome); }

/* ---------- the Space layer's key map (keys.js) ---------- */

#keyhud {
  position: fixed; z-index: 40;
  left: 50%; transform: translateX(-50%);
  bottom: calc(var(--bar-h) + var(--kb, 0px) + 10px);
  display: grid; gap: 4px;
  padding: 10px;
  border-radius: 12px;
  background: var(--chrome);
  border: 1px solid var(--rule);
  box-shadow: 0 6px 24px rgba(0,0,0,.18);
  pointer-events: none;
}
#keyhud[hidden] { display: none; }
.khrow { display: grid; grid-template-columns: repeat(4, 118px); gap: 4px; }
.khcell { display: flex; align-items: center; gap: 6px; padding: 4px 6px; border-radius: 7px;
          background: var(--paper); font-size: 12px; color: var(--ink-2); }
.khcell kbd { font: 600 11px/1 var(--mono); min-width: 18px; padding: 3px 4px; border-radius: 4px;
              border: 1px solid var(--rule); text-align: center; color: var(--ink); background: var(--paper-2); }
.khcell .khi { display: grid; place-items: center; width: 18px; }
.khcell .khi svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.khcell .khl { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.khcell.hit { background: var(--accent); color: var(--on-accent); }

/* ---------- a header over each pane (2026-10-19) ----------
   Side by side (panes.js sets data-panes-wide), every pane wears its own header and
   the top strip steps aside; on a phone the strip is the header of the one note on
   screen. The same gestures either way (topbar.js). */
.phead { display: none; }
[data-panes-wide] .phead {
  flex: 0 0 auto;
  display: flex; align-items: center;
  height: calc(var(--top-row) + 8px);
  padding: 0 10px;
  border-bottom: 1px solid var(--rule);
  background: var(--paper);
}
[data-panes-wide] #tabs { visibility: hidden; }
.ptab {
  flex: 1 1 auto; min-width: 0;
  height: var(--top-row);
  padding: 0 8px;
  text-align: left;
  font-size: 14px; font-weight: 600;
  color: var(--ink-3);
  border-radius: 8px;
  touch-action: none;           /* a drag on a header is a gesture of its own */
  transition: background var(--dur) var(--ease-smoother), color var(--dur) var(--ease-smoother);
}
.ptab .tt { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ptab:hover { background: var(--chrome); }
.ptab[aria-current="true"] { background: var(--chrome); color: var(--ink); box-shadow: inset 0 -2px 0 var(--accent); }
.ptab.dragging { position: relative; z-index: 3; opacity: .9; box-shadow: 0 0 0 2px var(--accent); cursor: grabbing; }

/* the note list that drops down from a header */
#notepick {
  position: fixed; z-index: 45;
  max-width: min(360px, calc(100vw - 16px));
  max-height: 55vh; overflow-y: auto;
  padding: 4px;
  border-radius: 10px;
  background: var(--paper);
  border: 1px solid var(--rule);
  box-shadow: 0 8px 28px rgba(0,0,0,.2);
}
#notepick[hidden] { display: none; }
.npick {
  display: block; width: 100%;
  min-height: 40px; padding: 0 12px;
  text-align: left; font-size: 15px;
  color: var(--ink); border-radius: 7px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.npick:hover, .npick.hot { background: var(--accent); color: var(--on-accent); }
.npick[aria-current="true"] { font-weight: 700; }

/* the selection menu's Text style selector opens this second row */
.selbar2 { margin-top: 4px; }
.selbar2[hidden] { display: none; }
.selgrp[aria-expanded="true"] { box-shadow: inset 0 0 0 1.5px var(--accent); }

/* the whole-line hold: a text style fills up while held; full means the whole line */
.fbtn { position: relative; }
.fbtn.charging { overflow: hidden; }
.fbtn.charging { box-shadow: 0 0 0 2px var(--accent); transform: scale(1.06); transition: transform var(--dur) var(--ease-smoother); }
.fbtn.charging::before {
  content: ""; position: absolute; inset: 0;
  background: color-mix(in srgb, var(--accent) 70%, transparent);
  transform-origin: left center;
  animation: line-charge var(--line-ms, 450ms) linear forwards;
  pointer-events: none;
}
@keyframes line-charge { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.fbtn.charged { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }

/* ---------- the font selector (ui/font.js) ---------- */
#fontpick {
  position: fixed; z-index: 60;
  min-width: 240px; padding: 6px;
  border-radius: 10px;
  background: var(--paper);
  border: 1px solid var(--rule);
  box-shadow: 0 8px 28px rgba(0,0,0,.2);
}
#fontpick[hidden] { display: none; }
.fphead { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
          color: var(--ink-3); padding: 8px 10px 4px; }
.fpopt { display: block; width: 100%; min-height: 40px; padding: 0 10px; text-align: left;
         font-size: 15px; color: var(--ink); border-radius: 7px; }
.fpopt:hover { background: var(--chrome); }
.fpopt[aria-checked="true"] { background: var(--accent); color: var(--on-accent); }

/* ---------- the hotkey trainer (ui/trainer.js) ---------- */
#train-panel { outline: none; }
.trn-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.trn-head h2 { font-size: 17px; margin: 0; flex: 1; }
.trn-modes { display: flex; gap: 4px; background: var(--chrome); padding: 3px; border-radius: 9px; }
.trn-modes button { min-height: 34px; padding: 0 12px; border-radius: 7px; font-size: 14px; color: var(--ink-2); }
.trn-modes button[aria-selected="true"] { background: var(--paper); color: var(--ink); font-weight: 600; box-shadow: 0 1px 2px rgba(0,0,0,.08); }
.trn-close { min-height: 40px; padding: 0 14px; background: var(--chrome); color: var(--ink); }
.trn-note { font-size: 13px; color: var(--danger); }
.trn-body { max-width: 640px; margin: 0 auto; }
.trn-sub { font-size: 14px; color: var(--ink-2); text-align: center; }
.trn-stats { display: flex; justify-content: center; gap: 28px; margin: 16px 0; }
.trn-stats div { display: flex; flex-direction: column; align-items: center; }
.trn-stats b { font-size: 24px; }
.trn-stats span { font-size: 12px; color: var(--ink-3); }
.trn-recent { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; margin: 8px 0 16px; }
.trn-recent span { font-size: 12px; padding: 4px 8px; border-radius: 999px; background: var(--chrome); color: var(--ink-2); }
.trn-start { display: block; margin: 18px auto; min-height: 48px; padding: 0 28px; font-size: 16px; }
.trn-progress { height: 6px; border-radius: 3px; background: var(--chrome); overflow: hidden; }
.trn-progress span { display: block; height: 100%; background: var(--accent); transition: width var(--dur) var(--ease-smoother); }
.trn-meta { display: flex; justify-content: space-between; font-size: 13px; color: var(--ink-2); margin: 8px 0 16px; }
.trn-card { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 28px 16px; border-radius: 14px;
            background: var(--paper-2); border: 2px solid var(--rule); transition: border-color var(--dur) var(--ease-smoother), background var(--dur) var(--ease-smoother); }
.trn-card.right { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 16%, var(--paper-2)); }
.trn-card.wrong { border-color: var(--danger); }
.trn-icon { font-size: 26px; }
.trn-icon svg { width: 34px; height: 34px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.trn-big { font-size: 26px; font-weight: 700; }
.trn-hint { font-size: 14px; color: var(--ink-3); font-family: var(--mono); }
.trn-feedback { min-height: 22px; margin-top: 10px; text-align: center; font-size: 15px; font-weight: 600; }
.trn-score { font-size: 56px; font-weight: 800; text-align: center; letter-spacing: -.02em; }
.trn-map { display: grid; gap: 4px; margin-top: 16px; }
.trn-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; }
.trn-cell { display: flex; align-items: center; gap: 6px; padding: 5px 7px; border-radius: 7px; background: var(--paper-2);
            font-size: 12px; color: var(--ink-2); min-width: 0; overflow: hidden; white-space: nowrap; }
.trn-cell kbd { font: 600 11px/1 var(--mono); padding: 3px 5px; border-radius: 4px; border: 1px solid var(--rule); color: var(--ink); background: var(--paper); }
.trn-cell .trn-i svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.9; }
.trn-cell.lit { background: var(--accent); color: var(--on-accent); }

/* the feedback panel (Ctrl+.) always opens above everything else, the trainer included */
#claude-panel { z-index: 55; }
.trn-card.shake { animation: trn-shake 260ms var(--ease-smoother); }
@keyframes trn-shake { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-6px); } 75% { transform: translateX(6px); } }

/* ---------- the move card: only on the old address (ui/move.js) ---------- */
#movecard {
  position: fixed; z-index: 52;
  left: 50%; transform: translateX(-50%);
  top: calc(var(--sa-top) + 10px);
  width: min(460px, calc(100vw - 20px));
  padding: 14px 16px;
  border-radius: 14px;
  background: var(--paper);
  border: 2px solid var(--accent);
  box-shadow: 0 10px 30px rgba(0,0,0,.22);
  font-size: 14px;
}
#movecard[hidden] { display: none; }
#movecard h3 { margin: 0 0 6px; font-size: 17px; }
#movecard p { margin: 6px 0; color: var(--ink-2); }
#movecard ol { margin: 6px 0; padding-left: 20px; }
#movecard li { margin: 3px 0; }
#movecard .mv-wait { color: var(--danger); }
#movecard .mv-note { font-size: 12px; color: var(--ink-3); }
.mv-btns { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.mv-btns .go { flex: 1 1 auto; min-height: 44px; }
.mv-btns .mv-later { background: var(--chrome); color: var(--ink); }
