/* octo.science landing — same look as octo note (typesafe.ai-inspired: one family, mono micro-labels, wide body
   tracking. Since 2026-10-10 it borrows the OCTO LAB LOG feel (soft cards,
   flat hairline cards, 4/3 px corners) while keeping the pastel palettes and
   the ink. Type: Host Grotesk = --item-size (content) + --ui (buttons);
   JetBrains Mono = --mono everywhere. No other sizes. */

@font-face {
  font-family: 'Host Grotesk';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url(/static/fonts/host-grotesk-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
    U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Host Grotesk';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url(/static/fonts/host-grotesk-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 300 500;
  font-display: swap;
  src: url(/static/fonts/jetbrains-mono-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
    U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Palette (2026-10-11, chosen by Horst): Celadon #B8D8BA, Beige #D9DBBC, Soft Apricot #FCDDBC,
   Cotton Candy #EF959D (default), Taupe Grey #69585F family for ink. Every text colour >= 4.8:1. */
/* `hidden` must win over any display rule (.link is display:flex, which kept
   'lock' in rooms and 'burn all' on an empty page visible). */
[hidden] { display: none !important; }

:root {
  --item-size: 21px;           /* notes, files, folders: one size */
  --bg: #EF959D;          /* Cotton Candy */
  --drop: rgba(242, 166, 173, .92);
  --panel: #f2a6ad;       /* tiles, one step lighter */
  --panel-2: #f5b4ba;     /* hover / focus */
  --fg: #2b2226;          /* taupe-black ink, 7.0:1 on cotton */
  --dim: #3a2d32;         /* 5.9:1 on cotton */
  --faint: #4a3a40;       /* labels, 4.8:1 on cotton, 6.9+ elsewhere */
  --line: rgba(43, 34, 38, .20);
  --line-2: rgba(43, 34, 38, .42);
  --accent: #2b2226;
  --warn: #6e1d0c;        /* 4.7:1 */
  --crit: #5c0a18;        /* 5.8:1 */
  --bw: 1.5px;            /* button / focus stroke */
  --r: 0px;               /* flat: no rounded boxes */
  --r-sm: 0px;            /* buttons, fields, toast */
  --ui: 15px;             /* Host Grotesk UI text (buttons) */
  --mono: 13px;           /* every JetBrains Mono label, link and glyph */
  --track: .06em;         /* every mono label's letter-spacing */
  --ease: cubic-bezier(.2, .7, .2, 1);
}

/* the other three fields. Same ink everywhere; theme.js picks one at random. */
/* Colour changes are applied instantly (see the note on html,body above), so
   .theming no longer stretches anything. Kept as a hook for the palette drift. */

/* palette: Celadon, Beige, Soft Apricot, Cotton Candy (default) + Taupe Grey as the ink family. */
:root[data-theme="celadon"] { --bg: #B8D8BA; --panel: #c6e0c8; --panel-2: #d1e7d3; --drop: rgba(198, 224, 200, .92); }
:root[data-theme="beige"]   { --bg: #D9DBBC; --panel: #e2e4c9; --panel-2: #e9ead5; --drop: rgba(226, 228, 201, .92); }
:root[data-theme="apricot"] { --bg: #FCDDBC; --panel: #fde6cd; --panel-2: #feecda; --drop: rgba(253, 230, 205, .92); }

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; background: var(--bg); color: var(--fg);
  font-family: 'Host Grotesk', Inter, -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: 100%; }
::selection { background: var(--fg); color: var(--bg); }
body { min-height: 100svh; display: flex; justify-content: center;
  padding: max(8vh, 40px) 28px calc(44px + env(safe-area-inset-bottom)); }
.wrap { position: relative; z-index: 1; width: 100%; max-width: 46rem; display: flex; flex-direction: column; gap: 34px; }

.micro { font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace; font-weight: 400;
  font-size: var(--mono); line-height: 1.2; letter-spacing: var(--track); text-transform: uppercase;
  color: var(--faint); font-variant-numeric: tabular-nums; }

@keyframes rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes pulse { 50% { opacity: .35; } }
@keyframes shake { 20%, 60% { transform: translateX(-7px); } 40%, 80% { transform: translateX(7px); } }
@keyframes wiggle { 0%, 100% { transform: rotate(-.35deg); } 50% { transform: rotate(.35deg); } }

/* ---------- header ---------- */
.top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; animation: rise .5s var(--ease) both; }
.brand { color: var(--fg); }
#status { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- board ---------- */
#board { display: flex; flex-direction: column; gap: 44px; }
.sec { display: flex; flex-direction: column; gap: 12px; animation: rise .5s var(--ease) both; }
.sec-head { display: flex; align-items: center; gap: 8px; min-height: 30px; }
.sec-title { color: var(--fg); flex: 1; min-width: 0; }
.sec-count { color: var(--faint); }
input.sec-title { background: transparent; border: 0; border-bottom: 1px solid var(--line-2); outline: none;
  padding: 4px 0; color: var(--fg); font: inherit; font-family: 'JetBrains Mono', monospace; font-size: var(--mono);
  letter-spacing: var(--track); text-transform: uppercase; }
input.sec-title:focus { border-bottom-color: var(--fg); }
.sec-tools { display: none; gap: 2px; }
.editing .sec-tools { display: inline-flex; }
.sec-tools .link { min-width: 32px; min-height: 32px; justify-content: center; color: var(--fg); }

.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 0; min-height: 64px;
  border-top: 1px solid var(--line-2); border-left: 1px solid var(--line-2); }
.grid:empty::after { content: "drop sites here"; display: flex; align-items: center; justify-content: center;
  grid-column: 1 / -1; border-right: 1px solid var(--line-2); border-bottom: 1px solid var(--line-2); color: var(--faint);
  font-family: 'JetBrains Mono', monospace; font-size: var(--mono); letter-spacing: var(--track); text-transform: uppercase; min-height: 88px; }

.tile { position: relative; display: flex; flex-direction: column; justify-content: space-between; gap: 22px;
  min-height: 124px; padding: 22px 18px 14px; background: transparent; overflow: hidden;
  border-right: 1px solid var(--line-2); border-bottom: 1px solid var(--line-2);
  color: var(--fg); text-decoration: none; cursor: pointer;
  transition: background .18s var(--ease), color .18s var(--ease);
  user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; }
html:not(.editing) .tile:hover { background: var(--fg); color: var(--bg); }
html:not(.editing) .tile:hover .micro { color: var(--bg); }
.tile:focus-visible { outline: var(--bw) solid var(--fg); outline-offset: -4px; }
.tile-name { font-size: var(--item-size); font-weight: 450; line-height: 1.12; letter-spacing: .005em; overflow-wrap: anywhere; }
.tile-host { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.tile-host span:first-child { min-width: 0; overflow-wrap: break-word; line-height: 1.3; }
.tile-arrow { flex: none; transition: transform .2s var(--ease); }
.tile:hover .tile-arrow { transform: translate(2px, -2px); }
.tile .del { position: absolute; top: 14px; right: 12px; display: none; width: 32px; height: 32px; align-items: center;
  justify-content: center; border: 0; background: var(--fg); color: var(--bg);
  font-size: 16px; line-height: 1; cursor: pointer; }
.editing .tile .del { display: inline-flex; }
.editing .tile { cursor: grab; outline: 1px dashed var(--line-2); outline-offset: -5px; }
.tile.lifted { opacity: .25; }
.drag-ghost { position: fixed; z-index: 20; pointer-events: none; margin: 0; background: var(--panel-2); border: 1px solid var(--fg);
  box-shadow: 0 14px 30px rgba(43, 34, 38, .28); transition: none; animation: none; }
.dragging, .dragging * { cursor: grabbing !important; user-select: none !important; }
.sec.sec-over .grid { outline: 1px dashed var(--line-2); outline-offset: 6px; }
.grid.target { outline: 1px dashed var(--fg); outline-offset: 6px; }

/* ---------- adder (edit mode) ----------
   Both forms are one row on desktop; on a phone the site form becomes
   name / address / [section][Add] and the section form stays name + button. */
.adder { display: flex; flex-direction: column; gap: 10px; padding: 18px 0 0; border-top: 1px solid var(--line-2);
  animation: rise .35s var(--ease) both; }
.add-row { display: flex; gap: 8px; align-items: stretch; }
.add-row > * { min-width: 0; }
.add-row .btn { flex: none; white-space: nowrap; }
.field { height: 40px; padding: 0 12px; background: transparent; color: var(--fg); border: 1px solid var(--line-2);
  border-radius: var(--r-sm); font: inherit; font-size: 16px; outline: none; }
#add-name { flex: 0 0 9.5rem; }
.field.grow { flex: 1 1 0; }
select.field { flex: 0 1 9rem; width: 100%; -webkit-appearance: none; appearance: none; padding: 0 30px 0 12px;
  text-overflow: ellipsis; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, var(--fg) 50%), linear-gradient(135deg, var(--fg) 50%, transparent 50%);
  background-position: calc(100% - 17px) 17px, calc(100% - 12px) 17px; background-size: 5px 5px, 5px 5px; background-repeat: no-repeat; }
.add-row .btn { height: 40px; }
.field:focus { border-color: var(--fg); background: var(--panel-2); }
.field::placeholder { color: var(--faint); opacity: .8; }
.add-sep { height: 0; border: 0; border-top: 1px solid var(--line); margin: 2px 0; }
@media (max-width: 560px) {
  #add-site { display: grid; grid-template-columns: minmax(0, 1fr) auto; }
  #add-name, #add-url { grid-column: 1 / -1; flex: none; width: 100%; }
  select.field { flex: none; }
}

/* ---------- colour ----------
   A colour is a NAME (taupe, ochre, ...). The shades live here, one set per mode.
   Light mode uses deep pigments (they sit on every pastel field the way the ink
   does, instead of shouting like a saturated sticker); dark mode uses lifted twins.
   A tile uses its own colour, else its section's. The colour shows as a wide band
   on the tile, a soft tint of the tile itself, and a rule under the section title. */
/* Accents are NEUTRALS: earthy, desaturated, drawn from the same warm family as the field. */
:root {
  --c-taupe: #69585F; --c-ochre: #715400; --c-clay: #8c3f2c; --c-olive: #475a2c;
  --c-slate: #35525f; --c-mauve: #6a3f60; --c-ink: var(--fg);
}
:root[data-mode="dark"] {
  --c-taupe: #d3c3cb; --c-ochre: #e6c56f; --c-clay: #eca391; --c-olive: #b9c98f;
  --c-slate: #9fc0cf; --c-mauve: #d4aecb;
}
[data-color="taupe"] { --bar: var(--c-taupe); } [data-color="ochre"] { --bar: var(--c-ochre); }
[data-color="clay"]  { --bar: var(--c-clay); }  [data-color="olive"] { --bar: var(--c-olive); }
[data-color="slate"] { --bar: var(--c-slate); } [data-color="mauve"] { --bar: var(--c-mauve); }
[data-color="ink"]   { --bar: var(--c-ink); }

/* a tile only ever wears ITS OWN effective colour: the section's --bar must not leak into bare tiles */
.tile:not([data-color]) { --bar: initial; }
.tile::before { content: ""; position: absolute; left: 0; top: 0; right: 0; height: 7px;
  background: var(--bar, transparent); transition: height .2s var(--ease); }
html:not(.editing) .tile:hover::before { height: 11px; }

/* section header: marker block + a rule in the section's colour */
.sec-head { padding-bottom: 9px; border-bottom: 2px solid var(--bar, var(--line)); }
.sec-bar { flex: none; position: relative; display: block; width: 14px; height: 24px; padding: 0; border: 0; background: none; }
.sec-bar::before { content: ""; position: absolute; left: 0; top: 1px; bottom: 1px; width: 14px;
  background: var(--bar, var(--line-2)); transition: transform .2s var(--ease); }
button.sec-bar { width: 32px; height: 32px; margin: -4px -9px -4px -9px; cursor: pointer; }
button.sec-bar::before { left: 9px; top: 6px; bottom: 6px; width: 14px; }
button.sec-bar:hover::before { transform: scale(1.15); }
button.sec-bar:focus-visible, .hue:focus-visible, .sw:focus-visible { outline: var(--bw) solid var(--fg); outline-offset: 2px; }
.sec-title { margin-left: 2px; }

/* edit mode: the colour dot lives bottom-right, where the arrow was */
.hue { position: absolute; right: 6px; bottom: 5px; width: 32px; height: 32px; padding: 0; border: 0; background: none;
  display: none; cursor: pointer; }
.hue::after { content: ""; position: absolute; left: 6px; top: 6px; width: 20px; height: 20px; border-radius: 50%;
  border: 1.5px dashed var(--faint); background: transparent; transition: transform .15s var(--ease); }
.hue::before { content: ""; position: absolute; left: 11px; top: 11px; width: 10px; height: 10px; border-radius: 50%;
  background: var(--bar, transparent); }
.hue[data-color]::after { border-color: var(--bar); }
.hue.own::after { border-style: solid; }          /* a colour of its own, not inherited from the section */
.hue:hover::after { transform: scale(1.12); }
.editing .hue { display: block; }
.editing .tile-arrow { visibility: hidden; }

/* swatch popover: 4 x 2 (none + 7 neutrals), round swatches */
.pop { position: fixed; z-index: 40; display: grid; grid-template-columns: repeat(4, 40px); gap: 10px; padding: 14px;
  background: var(--panel-2); border: 1px solid var(--fg); border-radius: var(--r);
  box-shadow: 0 12px 30px rgba(43, 34, 38, .24); animation: rise .15s var(--ease) both; }
html[data-mode="dark"] .pop { background: var(--panel-2); box-shadow: 0 12px 30px rgba(0, 0, 0, .55); }
.sw { position: relative; width: 40px; height: 40px; padding: 0; border: 0; border-radius: 50%; background: var(--bar, transparent);
  cursor: pointer; transition: transform .15s var(--ease); }
.sw:hover { transform: scale(1.08); }
.sw[aria-checked="true"] { box-shadow: 0 0 0 2px var(--panel-2), 0 0 0 4px var(--fg); }
.sw.none { background: none; border: 1.5px dashed var(--faint); }
.sw.none::after { content: ""; position: absolute; left: 7px; right: 7px; top: 50%; border-top: 1.5px solid var(--faint); transform: rotate(-45deg); }

/* ---------- bar ---------- */
.bar-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.bar-links { display: inline-flex; align-items: center; gap: 4px; }
.bar-row > *, .bar-links > * { white-space: nowrap; }
#lock:hover, #edit:hover { color: var(--fg); }
#edit[aria-pressed="true"] { color: var(--fg); text-decoration: underline; text-underline-offset: 4px; }
#local-clock { flex: none; color: var(--faint); letter-spacing: var(--track); }
.link.icon { padding: 0 6px; }
.link.icon svg { display: block; transition: transform .35s var(--ease); }
.link.icon:hover svg { transform: rotate(18deg); }
@media (pointer: coarse) { .link.icon { min-width: 34px; justify-content: center; } .link { min-height: 36px; } }

/* ---------- toast ---------- */
.toast { position: fixed; left: 50%; bottom: calc(30px + env(safe-area-inset-bottom)); transform: translate(-50%, 14px);
  display: flex; align-items: center; gap: 10px; padding: 10px 16px; background: var(--fg); border-radius: var(--r-sm);
  font-family: 'JetBrains Mono', monospace; font-size: var(--mono); font-weight: 500; letter-spacing: var(--track);
  text-transform: uppercase; color: var(--bg); opacity: 0; pointer-events: none;
  transition: opacity .25s var(--ease), transform .25s var(--ease); max-width: calc(100vw - 56px); z-index: 30; }
.toast.show { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }
.toast.bad { background: var(--crit); color: #fbe3ea; }
.toast .link { color: var(--bg); text-decoration: underline; text-underline-offset: 3px; padding: 0 4px; }

/* ---------- gate: _ _ _ _ _ ---------- */
html.locked .wrap, html.locked .toast { display: none; }
html:not(.locked) .gate { display: none; }
.slots { display: flex; gap: 16px; }
.slots i { width: 30px; }
.gate-msg { min-height: 16px; text-align: center; }
.gate.bad .gate-msg { color: var(--crit); }
@media (max-width: 480px) { .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } .tile { min-height: 108px; padding: 20px 14px 12px; } .slots { gap: 12px; } }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001s !important; transition-duration: .001s !important; }
}

/* ---------- buttons (from octo note) ---------- */
.btn {
  appearance: none;
  border: var(--bw) solid var(--fg);
  border-radius: var(--r-sm);
  background: var(--fg);
  color: var(--bg);
  font-family: inherit;
  font-size: var(--ui);
  font-weight: 500;
  letter-spacing: .01em;
  padding: 0 18px;
  height: 40px;
  min-width: 34px;
  cursor: pointer;
  transition: transform .18s var(--ease), background .18s var(--ease),
              color .18s var(--ease), opacity .18s;
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0) scale(.985); }
.btn:disabled { opacity: .4; cursor: default; transform: none; }
.btn.ghost { background: transparent; color: var(--fg); }
.btn.ghost:hover { background: var(--fg); color: var(--bg); }
.btn:focus-visible, .link:focus-visible { outline: var(--bw) solid var(--fg); outline-offset: 3px; }

.link {
  appearance: none;
  background: none;
  border: 0;
  padding: 0 6px;
  min-height: 30px;
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  color: var(--faint);
  text-decoration: none;
  transition: color .2s var(--ease);
}
.link:hover { color: var(--fg); }

.drop-hint {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: var(--drop);
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s var(--ease);
}
.composer.drag .drop-hint { opacity: 1; }
.drop-hint span {
  font-family: 'JetBrains Mono', monospace;
  font-size: var(--mono);
  font-weight: 500;
  letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--fg);
}

.bar-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 30px;
  margin-top: -6px;
}
#burn:hover { color: var(--crit); }

/* ---------- items ---------- */

.items { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.items:empty { display: none; }

.item {
  position: relative;
  padding: 15px 16px 19px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r);
  animation: rise .4s var(--ease) both;
  overflow: hidden;
  transition: border-color .2s var(--ease);
}
.item:hover { border-color: var(--line-2); }
.item.dying { animation: fade .45s var(--ease) both; }

.item-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.item-name {
  font-size: var(--item-size);
  font-weight: 450;
  line-height: 1.36;
  letter-spacing: .01em;
  word-break: break-word;
  min-width: 0;
}
.item-body {
  margin: 0;
  font-size: var(--item-size);
  font-weight: 450;
  line-height: 1.36;
  letter-spacing: .01em;
  color: var(--fg);
  white-space: pre-wrap;
  overflow-wrap: break-word;       /* break inside a word only if it can't fit a line on its own */
  max-height: calc(1.36em * 9);
  overflow: hidden;
  font-feature-settings: "ss01", "cv11";
}
.autolink {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .16em;
  text-decoration-color: var(--line-2);
  transition: text-decoration-color .2s var(--ease);
  overflow-wrap: anywhere;         /* a link moves to its own line first; only a link longer
                                      than the line is split mid-way */
}
.autolink:hover { text-decoration-color: var(--fg); }

.item-body.clamped {
  cursor: pointer;
  mask-image: linear-gradient(#000 72%, transparent);
  -webkit-mask-image: linear-gradient(#000 72%, transparent);
}
.item-body.open { max-height: none; mask-image: none; -webkit-mask-image: none; }

/* files inside one drop: quiet rows, no boxes */
.files { list-style: none; margin: 0; padding: 0; }
.file {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 3px 0;
  animation: rise .3s var(--ease) both;
}
.file.dying { animation: fade .3s var(--ease) both; }
.file-name {
  flex: 1 1 auto;
  min-width: 0;
  color: var(--fg);
  font-size: var(--item-size);
  font-weight: 450;
  line-height: 1.36;
  letter-spacing: .01em;
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  border-bottom: 1px solid transparent;
  transition: border-color .2s var(--ease);
}
.file-name:hover { border-bottom-color: var(--fg); }
.file-size { flex: 0 0 auto; }
.file-x {
  flex: 0 0 auto;
  font-family: 'JetBrains Mono', monospace;
  font-size: var(--mono);
  line-height: 1;
  min-height: 26px;
  min-width: 26px;
  justify-content: center;
  opacity: .55;
  transition: opacity .2s var(--ease), color .2s var(--ease);
}
.file-open {
  flex: 0 0 auto;
  color: var(--faint);
  font-family: 'JetBrains Mono', monospace;
  font-size: var(--mono);
  letter-spacing: var(--track);
  text-transform: uppercase;
  min-height: 26px;
  padding: 0 4px;
}
.file-open:hover { color: var(--fg); }
.file:hover .file-x, .file-x:focus-visible { opacity: 1; }
.file-x:hover { color: var(--crit); }
@media (pointer: coarse) {
  .file { padding: 5px 0; }
  .file-x { opacity: 1; min-height: 34px; min-width: 34px; }
  .file-open { min-height: 34px; padding: 0 8px; }
}

/* one row, always: clock · size on the left (size gives way first), actions on the right */
.item-meta { display: flex; align-items: center; gap: 10px; flex-wrap: nowrap; margin-top: 8px; }
.item-meta .micro { white-space: nowrap; }
.item-meta .size { min-width: 0; overflow: hidden; text-overflow: ellipsis; color: var(--faint); }
.name-size { margin-left: 10px; color: var(--faint); white-space: nowrap; vertical-align: 2px; }
.item-meta .size::before { content: "\00b7"; margin-right: 10px; color: var(--faint); }

.clock { color: var(--fg); font-weight: 500; }
.clock.warn { color: var(--warn); }
.clock.crit { color: var(--crit); animation: pulse 1s infinite steps(1, end); }

.acts { display: flex; flex: 0 0 auto; flex-wrap: nowrap; gap: 2px; margin-left: auto; }
.acts .link { min-width: 32px; color: var(--faint); font-family: 'JetBrains Mono', monospace;
  font-size: var(--mono); letter-spacing: var(--track); text-transform: uppercase;
  min-height: 30px; display: inline-flex; align-items: center; padding: 0 8px; }
.acts .link:hover { color: var(--fg); }
.acts .link.kill:hover { color: var(--crit); }

/* life bar: ink on a faint ink track, flush to the item's bottom edge */
.life {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  width: 100%;
  background: var(--line);
  overflow: hidden;
}
.life i {
  display: block;
  height: 100%;
  width: 100%;
  background: var(--fg);
  transform-origin: left center;
  transition: transform .25s linear, background .3s var(--ease);
}
.life i.warn { background: var(--warn); }
.life i.crit { background: var(--crit); }

/* stop-upload × next to "uploading": same family as the per-file × */
.up-state { display: inline-flex; align-items: center; gap: 6px; }
.up-x {
  font-family: 'JetBrains Mono', monospace;
  font-size: var(--mono);
  line-height: 1;
  min-height: 26px;
  min-width: 26px;
  justify-content: center;
  opacity: .7;
  transition: opacity .2s var(--ease), color .2s var(--ease);
}
.up-x:hover, .up-x:focus-visible { opacity: 1; color: var(--crit); }
@media (pointer: coarse) { .up-x { opacity: 1; min-height: 34px; min-width: 34px; } }

/* upload progress: deliberately unlike the life bar (2 px, solid, shrinking).
   Thicker, hatched with ink stripes that march left to right, and it GROWS.
   The fill is revealed with clip-path, not scaleX, so the stripes never
   stretch. */
.up {
  margin-top: 12px;
  height: 5px;
  background: var(--line);
  overflow: hidden;
  position: relative;
}
.up i {
  display: block;
  height: 100%;
  width: 100%;
  background-image: repeating-linear-gradient(-45deg,
    var(--fg) 0 3px, transparent 3px 6px);
  background-size: 8.4853px 100%;      /* 6 px stripe period / cos 45deg: seamless loop */
  clip-path: inset(0 100% 0 0);
  transition: clip-path .2s var(--ease);
  animation: march .6s linear infinite;
}
.up.indet i {
  clip-path: inset(0 0 0 0);
  opacity: .45;                        /* size unknown yet: stripes march, no fill */
}

/* ---------- code gate (from octo note, 5 slots) ---------- */
/* ---------- code gate: four underscores, _ _ _ _ ----------
   Locked: only the gate shows; the notes UI isn't rendered at all. */
.gate { display: none; }
html.locked .wrap, html.locked .toast { display: none; }
html.pending .gate { visibility: hidden; }        /* no flash of ____ for unlocked browsers */
html.locked .gate {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  margin-top: 18vh;
  width: 100%;
}
.gate-box {
  position: relative;
  display: block;
  padding: 10px 14px;
  cursor: text;
}
.slots { display: flex; gap: 20px; }
.slots i {
  display: block;
  position: relative;
  width: 34px;
  height: 46px;
  border-bottom: 2px solid var(--line-2);
  transition: border-color .2s var(--ease);
}
.slots i.on { border-bottom-color: var(--fg); }          /* filled */
.slots i.on::after {                                      /* a dot, never the digit */
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  width: 11px; height: 11px;
  margin: -5.5px 0 0 -5.5px;
  border-radius: 50%;
  background: var(--fg);
  animation: rise .18s var(--ease);
}
.slots i.cur { border-bottom-color: var(--fg); animation: pulse 1.1s ease-in-out infinite; }
.gate.bad .slots { animation: shake .36s var(--ease); }
.gate.bad .slots i { border-bottom-color: var(--crit); }
.gate.wait .slots i { border-bottom-color: var(--line); animation: none; }
/* the real input sits invisibly on top of the slots: native keyboard, paste,
   autofill-off, screen readers, and the whole area is the hit target */
#pin {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  border: 0;
  padding: 0;
  font-size: 16px;            /* no iOS zoom-on-focus */
  color: transparent;
  caret-color: transparent;
  background: transparent;
}
.gate-msg { min-height: 16px; text-align: center; }
.gate.bad .gate-msg { color: var(--crit); }
@keyframes shake {
  20%, 60% { transform: translateX(-7px); }
  40%, 80% { transform: translateX(7px); }
}
@media (prefers-reduced-motion: reduce) {
  .gate.bad .slots, .slots i.cur, .slots i.on::after { animation: none; }
}
/* ---------- dark mode (2026-10-03) ----------
   Light/dark is a separate axis from the palette. Dark inverts the pair: a much
   darker field with warm cream ink (never pure white, same reasoning as the
   trailer card). Every palette gets a dark twin, so the random colour drift
   keeps working but stays deep.

   Specificity note: these selectors are `:root[data-mode="dark"][data-theme=X]`,
   which outranks the light `:root[data-theme=X]` rule above — no !important
   needed. The colour is applied to the root AND to body, because body is what
   paints the page. */
/* INVERSE: the palette becomes the ink. Field = a deep Taupe Grey (#69585F family), text/lines/buttons = the
   active pastel (cotton / celadon / beige / apricot), so the colour drift still runs in dark mode. */
:root[data-mode="dark"], html[data-mode="dark"] body {
  --bg: #322a2e; --panel: #3a3136; --panel-2: #42383e; --drop: rgba(58, 49, 54, .94);
  --warn: #f0b45a; --crit: #ff9a8a;
  --ink-on: #322a2e;                       /* text on a button filled with the ink */
}
html[data-mode="dark"], :root[data-mode="dark"] body { --fg: #EF959D; --accent: #EF959D; --dim: #e08c94; --faint: #dc8a92;
  --line: rgba(239, 149, 157, .22); --line-2: rgba(239, 149, 157, .46); --ink: #EF959D; }
html[data-mode="dark"][data-theme="celadon"], :root[data-mode="dark"][data-theme="celadon"] body { --fg: #B8D8BA; --accent: #B8D8BA; --dim: #adcaaf; --faint: #9db59e;
  --line: rgba(184, 216, 186, .22); --line-2: rgba(184, 216, 186, .46); --ink: #B8D8BA; }
html[data-mode="dark"][data-theme="beige"], :root[data-mode="dark"][data-theme="beige"] body { --fg: #D9DBBC; --accent: #D9DBBC; --dim: #cccdb1; --faint: #b8b8a0;
  --line: rgba(217, 219, 188, .22); --line-2: rgba(217, 219, 188, .46); --ink: #D9DBBC; }
html[data-mode="dark"][data-theme="apricot"], :root[data-mode="dark"][data-theme="apricot"] body { --fg: #FCDDBC; --accent: #FCDDBC; --dim: #eccfb1; --faint: #d4b9a0;
  --line: rgba(252, 221, 188, .22); --line-2: rgba(252, 221, 188, .46); --ink: #FCDDBC; }
html[data-mode="dark"], html[data-mode="dark"] body { background-color: #322a2e; }

/* buttons invert: the fill is the ink colour, so in dark it is cream on dark text */
html[data-mode="dark"] .btn       { background: var(--ink); border-color: var(--ink); color: var(--ink-on); }
html[data-mode="dark"] .btn.ghost { background-color: transparent; color: var(--ink); }
html[data-mode="dark"] .btn.ghost:hover { background-color: var(--ink); color: var(--ink-on); }
html[data-mode="dark"] .toast     { background-color: var(--ink); color: var(--ink-on); }
html[data-mode="dark"] .drop-hint { background-color: rgba(58, 49, 54, .94); }


/* five slots are narrower than octo note's four */
.slots { gap: 14px; }
.slots i { width: 32px; }
@media (max-width: 480px) { .slots { gap: 10px; } .slots i { width: 28px; } }

/* footer: the hint gives way, the controls never leave the screen */
#hint { min-width: 0; flex: 1 1 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar-links { flex: none; }
@media (max-width: 560px) { #hint { display: none; } .bar-row { justify-content: flex-end; } }

/* tile picker has two leading choices (follow section, none) + 7 colours = 3 x 3 */
.pop3 { grid-template-columns: repeat(3, 40px); }
.sw.inherit { background: none; border: 1.5px dashed var(--faint); }
.sw.inherit::after { content: ""; position: absolute; left: 11px; top: 11px; width: 14px; height: 14px; border-radius: 50%; background: var(--faint); opacity: .55; }
/* a tile with no colour at all: dashed ring crossed out */
.hue.off::after { border-color: var(--faint); }
.hue.off::before { left: 8px; right: 8px; top: 15px; width: auto; height: 0; border-radius: 0; background: none; border-top: 1.5px solid var(--faint); transform: rotate(-45deg); }
