/* Aiko's screens: Material Design 3 components, hand-rolled, on the tokens in
   tokens.css (each page links it first, beside this file, so the two load in parallel) — the design system's one source of colour, shape, type, spacing,
   motion and elevation. This file never holds a colour value: it names a token.
   See docs/v4/design-system.md. */
@import url('https://fonts.googleapis.com/css2?family=Google+Sans+Flex:opsz,wght@6..144,300..700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@24,400,0..1,0&icon_names=add,add_photo_alternate,alarm,approval,archive,arrow_back,arrow_upward,badge,bedtime,block,cake,cancel,chat,check,check_circle,checklist,chevron_right,close,content_copy,delete,description,edit,error,event,event_note,event_repeat,expand_less,expand_more,favorite,feedback,forum,help,hide_image,history,image,lightbulb,link,logout,mail,menu_book,mic,monitoring,more_horiz,more_vert,nights_stay,notifications_active,notifications_off,notifications_paused,open_in_new,pending,person,photo_camera,priority_high,psychology,push_pin,remove_circle_outline,repeat,reply,rule,schedule,settings,smart_toy,snooze,sports_score,star,stop,sunny,sync,task_alt,terminal,thumb_down,thumb_up,trending_down,trending_flat,trending_up,undo,verified,view_agenda,visibility,warning&display=block');

/* Layout only: safe areas and the nav's footprint (the rest is in tokens.css). */
:root {
  /* Safe areas: the Android app passes its own (app.js), a browser uses env() */
  --safe-top: var(--inset-top, env(safe-area-inset-top, 0px));
  --safe-bottom: var(--inset-bottom, env(safe-area-inset-bottom, 0px));
  --safe-left: var(--inset-left, env(safe-area-inset-left, 0px));
  --safe-right: var(--inset-right, env(safe-area-inset-right, 0px));
  --nav-h: 64px; --rail-w: 0px;
}

/* ── base ─────────────────────────────────────────────────────────────── */
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
[hidden] { display: none !important; } /* over any component's own display (.icon-btn) */
html { background: var(--md-surface); }
body {
  margin: 0; min-height: 100dvh; background: var(--md-surface); color: var(--md-on-surface);
  font: 400 var(--text)/var(--text-line) var(--font); letter-spacing: .1px; font-optical-sizing: auto;
  padding: 0 var(--safe-right) calc(var(--nav-h) + var(--safe-bottom)) calc(var(--rail-w) + var(--safe-left));
}
a { color: var(--md-primary); }
h1, h2, h3, p { margin: 0; }
ul { list-style: none; margin: 0; padding: 0; }
button, input, textarea { font: inherit; color: inherit; letter-spacing: inherit; }
:focus-visible { outline: 3px solid var(--md-secondary); outline-offset: 2px; }
.icon {
  font-family: 'Material Symbols Rounded'; font-style: normal; font-weight: 400; font-size: var(--icon); line-height: 1;
  width: 1em; height: 1em; overflow: hidden; display: inline-block; flex: none; user-select: none;
  font-variation-settings: 'FILL' 0; font-feature-settings: 'liga'; letter-spacing: normal; /* spacing breaks the ligature */
}
.fill { font-variation-settings: 'FILL' 1; }

/* Typography scale */
.headline { font-size: var(--text-title); line-height: var(--text-title-line); font-weight: 400; }
.title-m { font-size: var(--text); line-height: var(--text-line); font-weight: 500; }
.title-s { font-size: var(--text); line-height: var(--text-line); font-weight: 500; letter-spacing: .1px; }
.body-m, .meta { font-size: var(--text); line-height: var(--text-line); letter-spacing: .2px; }
.body-s { font-size: var(--text-small); line-height: var(--text-small-line); letter-spacing: .4px; }
.label-m, .sub { font-size: var(--text-small); line-height: var(--text-small-line); font-weight: 500; letter-spacing: .5px; }
/* A small heading over what it names (Review's parts and records, Memory's Notes, a Routine's facts, a tag row). */
.sub { color: var(--md-on-surface-variant); }
h3.sub { margin: var(--space-4) var(--space-1) var(--space-2); }
.meta { color: var(--md-on-surface-variant); }

/* Spacing utilities, on the 4px grid: margin-top only (a stack's rhythm). */
.mt-1 { margin-top: var(--space-1); }
.mt-2 { margin-top: var(--space-2); }
.mt-4 { margin-top: var(--space-4); }
/* A line of explanation above a screen's list. */
.intro { margin: var(--space-1) var(--space-1) 0; }

/* ── top app bar ──────────────────────────────────────────────────────── */
.bar {
  position: sticky; top: 0; z-index: 5; display: flex; align-items: center; gap: 4px;
  min-height: calc(64px + var(--safe-top)); padding: var(--safe-top) 4px 0 16px;
  background: var(--md-surface); transition: background .2s var(--ease), transform .2s var(--ease);
}
.bar.scrolled { background: var(--md-surface-container); }
/* Chat: scrolling down the thread (index.html). The status-bar strip stays, in the bar's own colour, so the thread never
   shows under the phone's clock and icons; what the bar held fades out of it. */
.bar.away { transform: translateY(calc(var(--safe-top) - 100%)); }
.bar > * { transition: opacity .2s var(--ease); }
.bar.away > * { opacity: 0; pointer-events: none; }
.bar h1 { flex: 1; font-size: var(--text-title); line-height: var(--text-title-line); font-weight: 400; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bar .icon-btn:first-child { margin-left: -12px; }
.brand { display: flex; align-items: center; gap: 10px; }
.mark { width: 28px; height: 28px; flex: none; }

main { max-width: 840px; margin: 0 auto; padding: 8px 16px 32px; }

/* ── buttons (state layers by colour-mix; 48px touch target via ::after) ─ */
.btn, .icon-btn, .chip {
  --bg: transparent; --fg: var(--md-primary);
  position: relative; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  border: 0; cursor: pointer; background: var(--bg); color: var(--fg); text-decoration: none;
  transition: background .15s linear, border-radius .3s var(--spring);
}
/* A small button keeps a 48px tap area around its box (a switch, the Chat thumbs, the build line too). */
.btn::after, .chip::after, .icon-btn::after, .switch::after, .build::after {
  content: ''; position: absolute; left: 50%; top: 50%; width: max(100%, 48px); height: max(100%, 48px); transform: translate(-50%, -50%);
}
.btn:hover, .icon-btn:hover, .chip:hover { background: color-mix(in srgb, var(--fg) var(--state-hover), var(--bg)); }
.btn:active, .icon-btn:active, .chip:active { background: color-mix(in srgb, var(--fg) var(--state-press), var(--bg)); }
.btn { min-height: 40px; padding: 0 24px; border-radius: var(--r-full); font-size: var(--text); font-weight: 500; letter-spacing: .1px; }
.btn:active { border-radius: var(--r-md); }           /* M3 Expressive: the shape morphs when pressed */
.btn .icon { font-size: var(--icon-m); margin-left: -8px; }
.btn.filled { --bg: var(--fill-brand); --fg: var(--on-fill-brand); }
.btn.tonal { --bg: var(--fill-tonal); --fg: var(--on-fill-tonal); }
.btn.outlined { box-shadow: inset 0 0 0 1px var(--md-outline-variant); --fg: var(--md-on-surface-variant); }
.btn.text { padding: 0 12px; }
.btn.danger { --bg: var(--fill-danger); --fg: var(--on-fill-danger); }
.icon-btn { width: 48px; height: 48px; border-radius: var(--r-full); --fg: var(--md-on-surface-variant); flex: none; }
.icon-btn.filled { --bg: var(--fill-brand); --fg: var(--on-fill-brand); }
.icon-btn.danger { --bg: var(--md-error-container); --fg: var(--md-on-error-container); }
.chip.danger { --bg: var(--md-error-container); --fg: var(--md-on-error-container); }
.btn:disabled, .icon-btn:disabled, .chip:disabled { --fg: color-mix(in srgb, var(--md-on-surface) var(--state-disabled-fg), transparent); --bg: color-mix(in srgb, var(--md-on-surface) var(--state-disabled-bg), transparent); cursor: default; }
.chip {
  min-height: 32px; padding: 0 12px 0 8px; border-radius: var(--r-sm); font-size: var(--text); font-weight: 500;
  box-shadow: inset 0 0 0 1px var(--md-outline-variant); --fg: var(--md-on-surface-variant);
}
.chip .icon { font-size: var(--icon-m); color: var(--md-primary); }
.chip:not(:has(.icon)) { padding: 0 12px; } /* no leading icon: even sides */
.acts { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 12px; }
.pro .acts { margin-top: var(--space-2); }
.foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 8px; margin: 4px -8px -8px 0; }
.foot .badges { margin: 0; align-items: center; }
.foot .acts { margin: 0 0 0 auto; gap: 4px; }
.acts.end { justify-content: flex-end; }
.acts.center { justify-content: center; }
/* Review's 1-5 rating: five equal buttons. */
.acts.rating { margin: 0; gap: var(--space-1); }
.acts.rating .btn { flex: 1; }

/* ── navigation bar (compact) and rail (expanded, ≥840px) ─────────────── */
.nav {
  position: fixed; z-index: 10; left: 0; right: 0; bottom: 0; display: flex; justify-content: space-around;
  height: calc(var(--nav-h) + var(--safe-bottom)); padding: 0 var(--safe-right) var(--safe-bottom) var(--safe-left);
  background: var(--md-surface-container);
}
.nav a {
  flex: 1; max-width: 120px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  color: var(--md-on-surface-variant); text-decoration: none; font-size: var(--text-small); line-height: var(--text-small-line); font-weight: 500; letter-spacing: .5px;
}
.nav .pill { display: grid; place-items: center; width: 56px; height: 32px; border-radius: var(--r-full); transition: background .2s var(--ease); }
.nav a:hover .pill { background: color-mix(in srgb, var(--md-on-surface) var(--state-hover), transparent); }
.nav a.on { color: var(--md-on-surface); }
.nav a.on .pill { background: var(--fill-tonal); color: var(--on-fill-tonal); }
.nav a.on .icon { font-variation-settings: 'FILL' 1; }
.nav .mark { display: none; }
@media (min-width: 840px) {
  :root { --nav-h: 0px; --rail-w: 96px; }
  .nav {
    top: 0; right: auto; width: calc(var(--rail-w) + var(--safe-left)); height: auto; flex-direction: column; justify-content: flex-start;
    gap: 12px; padding: calc(var(--safe-top) + 20px) 0 0 var(--safe-left); background: var(--md-surface);
  }
  .nav a { flex: none; height: 64px; }
  .nav .mark { display: block; margin: 0 auto 28px; width: 32px; height: 32px; }
  .bar .mark { display: none; }
  .bar { padding-left: 24px; }
  main { padding: 8px 24px 40px; }
}
/* Typing hides the bar on a phone, so the keyboard has the room. */
@media (max-width: 839px) { body:has(.composer textarea:focus) { --nav-h: 0px; } body:has(.composer textarea:focus) .nav { display: none; } }

/* ── lists (M3 Expressive grouped list: tight gaps, rounded ends) ──────── */
.section { margin: 24px 4px 8px; color: var(--md-primary); font-size: var(--text); line-height: var(--text-line); font-weight: 500; display: flex; justify-content: space-between; }
.section .meta { font-weight: 400; }
.group { display: flex; flex-direction: column; gap: 2px; }
.row {
  display: flex; gap: 16px; align-items: flex-start; padding: 12px 8px 12px 16px; min-height: 56px;
  background: var(--md-surface-container-low); border-radius: var(--r-xs); overflow-wrap: anywhere;
}
.row:first-child { border-top-left-radius: var(--r-lg); border-top-right-radius: var(--r-lg); }
.row:last-child { border-bottom-left-radius: var(--r-lg); border-bottom-right-radius: var(--r-lg); }
.row > .main { flex: 1; min-width: 0; padding: 2px 0; }
.row > .lead { color: var(--md-on-surface-variant); margin-top: 2px; }
.row > .icon-btn { margin: -10px 0; }
a.row { color: inherit; text-decoration: none; align-items: center; }
a.row:hover, .row.tap:hover { background: color-mix(in srgb, var(--md-on-surface) var(--state-hover), var(--md-surface-container-low)); cursor: pointer; }
/* A closed row fades, but not its state line, which may hold an Undo. */
.row.gone > :not(.main):not(.state), .row.gone > .main > :not(.state):not(summary), .row.gone > .main > summary > :not(.state) { opacity: var(--emphasis-gone); }
.row.gone .title { text-decoration: line-through; }
/* A compact row (design-system.md § Type and density): the words over a small line, then its buttons at the end,
   each a 48px target. Chat's card items, and the rows of Items, Log and Memory. */
.row.dense { padding: 4px 0 4px 12px; min-height: 48px; gap: 0; align-items: center; }
.row.dense > .btn { min-height: 32px; padding: 0 12px; margin-right: 4px; }
.row.dense > .icon-btn { margin: -4px 0; }
.row.dense > .check { margin: -4px -4px -4px -12px; } /* Items: the circle leads the row */
.row.dense > .avatar { width: 32px; height: 32px; margin-right: var(--space-3); }
.row.dense > .lead { font-size: var(--icon-m); margin: 2px var(--space-3) 0 0; align-self: flex-start; }
.row.dense .main > summary { display: block; min-height: 0; font: inherit; }
.row.dense .meta { display: flex; flex-wrap: wrap; align-items: center; gap: 0 8px; font-size: var(--text-small); line-height: var(--text-small-line); }
.row.dense .meta .badge { padding: 0 6px; }
/* When it's due, as plain small words; late is in the error colour. */
.row.dense .when .badge { padding: 0; background: none; color: inherit; }
.row.dense .when .badge.due { color: var(--md-error); }
.row.dense .state { margin-top: 2px; font-size: var(--text-small); }
.row.dense .state .icon { font-size: var(--icon-s); }
.row.dense .why { margin-top: 4px; font-size: var(--text-small); line-height: var(--text-small-line); }
/* A row's longer words (an item's detail and why, a run's summary) as small lines: two at most until the row is tapped (.open). */
.row.dense .note { margin-top: 2px; color: var(--md-on-surface-variant); font-size: var(--text-small); line-height: var(--text-small-line); white-space: pre-wrap; }
.row.dense:not(.open) .note { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.row.dense .note .icon { font-size: var(--icon-s); vertical-align: -2px; color: var(--md-tertiary); }
.row.dense .main.tap { cursor: pointer; }
.row.dense > .main:last-child { padding-right: var(--space-3); } /* nothing after the words: keep them off the edge */
.row.dense .flag .icon { font-size: var(--icon-s); vertical-align: -3px; margin-right: 2px; color: var(--md-primary); } /* inline, so the line's · sit as on every meta line */
/* A row's words that link elsewhere (More, Schedule's day plan), then its ›. */
a.row.dense > .chev { margin-right: var(--space-2); color: var(--md-on-surface-variant); }
/* A row's outcome in place of its button (Review's Undone). */
.row.dense > .state { margin: 0 var(--space-3); }
/* The one expand pattern. A record that opens in place (Memory's people and interests, Rules, Skills, the Guide's sections,
   Review's passing criteria, a Routine's method and prompt): a <details> whose summary is its row, then all about it. */
.group > .opens { background: var(--md-surface-container-low); border-radius: var(--r-xs); }
.group > .opens:first-child { border-top-left-radius: var(--r-lg); border-top-right-radius: var(--r-lg); }
.group > .opens:last-child { border-bottom-left-radius: var(--r-lg); border-bottom-right-radius: var(--r-lg); }
.opens > summary.row { background: none; border-radius: inherit; font-weight: 400; list-style: none; padding-right: var(--space-2); }
.opens > summary::-webkit-details-marker { display: none; }
.opens > summary .chev { color: var(--md-on-surface-variant); transition: transform .2s var(--ease); }
.opens[open] > summary .chev { transform: rotate(90deg); }
.opens:not([open]) > summary .meta { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.opens:not([open]) > summary .text { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } /* Rules: a long rule, whole once opened */
.opens > .body { padding: 0 var(--space-2) var(--space-2) var(--space-3); }
.opens > .body > .acts { margin-top: 0; }
/* Inside it a card is flat (a skill's notes box), a document keeps its outline (a method), and rows sit a tone up. */
.opens > .body > .card:not(.outlined) { margin: 0; padding: 0; background: none; }
.opens > .body > .card.outlined { margin: var(--space-2) 0 0; padding: var(--space-3); }
.opens > .body .group > .row { background: var(--md-surface-container); }
/* Items, Log, Memory, Rules, Skills (main.dense): tighter section heads, and a fold line (Items' suggestions) in line with them. */
main.dense .section { margin: var(--space-3) var(--space-1) var(--space-1); }
main.dense .fold-line > summary { padding: 9px var(--space-1); }
.empty { padding: 32px 16px; text-align: center; color: var(--md-on-surface-variant); }
.empty .icon { font-size: var(--icon-l); display: block; margin: 0 auto 8px; color: var(--md-outline); }
/* An empty section inside a page (fill's `line`): one line, not the whole-list state above. */
.empty.line { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-1); text-align: left; }
.empty.line .icon { font-size: var(--icon-m); margin: 0; }
.badge { display: inline-flex; align-items: center; gap: 4px; border-radius: var(--r-sm); padding: 2px 8px; font-size: var(--text-small); line-height: var(--text-small-line); font-weight: 500; background: var(--md-surface-container-highest); color: var(--md-on-surface-variant); }
.badge .icon { font-size: var(--icon-s); }
.badge.due { background: var(--md-error-container); color: var(--md-on-error-container); }
.badge.ok { background: var(--md-primary-container); color: var(--md-on-primary-container); }
/* An item's type: whose move it is. */
.badge.job-things { background: var(--job-things-bg); color: var(--job-things-fg); }
.badge.job-follow { background: var(--job-follow-bg); color: var(--job-follow-fg); }
.badge.job-do { background: var(--job-do-bg); color: var(--job-do-fg); }
.badge.tert { background: var(--md-tertiary-container); color: var(--md-on-tertiary-container); }
.badges { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.badges.summary { margin: 0 var(--space-1) var(--space-3); }
.check {
  width: 48px; height: 48px; margin: -12px -4px -12px -12px; display: grid; place-items: center;
  border: 0; background: none; cursor: pointer; color: var(--md-on-surface-variant); border-radius: var(--r-full);
}
.check:hover { background: color-mix(in srgb, var(--md-primary) var(--state-hover), transparent); color: var(--md-primary); }

/* ── cards ─────────────────────────────────────────────────────────────── */
.card { background: var(--md-surface-container-low); border-radius: var(--r-xl); padding: 16px 20px 20px; margin: 8px 0; }
.card.outlined { background: var(--md-surface); box-shadow: inset 0 0 0 1px var(--md-outline-variant); }
/* Review's proposed change: the headline of its card, in regular weight. */
.proposal-change { margin-top: var(--space-1); font-weight: 400; }
/* Review: a lead line under a section title, the thumbs stat's slash, and a proposal's evidence toggle. */
.lede { margin: 0 var(--space-1) var(--space-2); }
.slash { margin: 0 2px; }
.btn.evidence { margin: var(--space-1) 0 0 calc(-1 * var(--space-3)); }

/* ── text fields ───────────────────────────────────────────────────────── */
.field { display: block; position: relative; margin: 16px 0; }
/* A row of labelled selects and short inputs (schedule times, a date, a topic). */
.pick { display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-4); margin-top: var(--space-3); }
.pick:empty { display: none; }
.pick label { display: flex; flex-direction: column; gap: var(--space-1); font-size: var(--text-small); line-height: var(--text-small-line); color: var(--md-on-surface-variant); }
.pick select, .pick input:not([type=checkbox]) { min-height: 48px; min-width: 112px; padding: 0 var(--space-3); border-radius: var(--r-xs); border: 1px solid var(--md-outline);
  background: var(--md-surface-container-low); color: var(--md-on-surface); font: inherit; font-size: var(--text-input); }
.pick input[type=number] { width: 96px; min-width: 0; }
.pick select:focus, .pick input:focus { outline: 2px solid var(--md-primary); outline-offset: -1px; }
.field input, .field textarea, .field select {
  width: 100%; min-height: 56px; padding: 16px; border-radius: var(--r-xs); border: 1px solid var(--md-outline);
  background: transparent; font-size: var(--text-input); line-height: var(--text-input-line); resize: vertical;
}
.field select { font-family: inherit; color: inherit; } /* a select in a form is a field too (an interest's Kind) */
.field textarea { min-height: 96px; }
.field input:focus, .field textarea:focus, .field select:focus { outline: none; border: 2px solid var(--md-primary); padding: 15px; }
.field > span { position: absolute; left: 12px; top: -8px; padding: 0 4px; font-size: var(--text-small); line-height: var(--text-small-line); background: var(--bgc, var(--md-surface)); color: var(--md-on-surface-variant); }
.field:focus-within > span { color: var(--md-primary); }
.field small { display: block; margin: 4px 16px 0; font-size: var(--text-small); line-height: var(--text-small-line); color: var(--md-on-surface-variant); }

/* ── switch ────────────────────────────────────────────────────────────── */
.switch { appearance: none; position: relative; width: 52px; height: 32px; margin: 0; border-radius: var(--r-full); flex: none; cursor: pointer;
  background: var(--md-surface-container-highest); box-shadow: inset 0 0 0 2px var(--md-outline); transition: background .2s var(--ease); }
.switch::before { content: ''; position: absolute; left: 8px; top: 8px; width: 16px; height: 16px; border-radius: 50%; background: var(--md-outline); transition: all .3s var(--spring); }
.switch:checked { background: var(--fill-brand); box-shadow: inset 0 0 0 2px var(--md-primary); }
.switch:checked::before { left: 24px; top: 4px; width: 24px; height: 24px; background: var(--on-fill-brand); }
.switch:disabled { opacity: var(--state-disabled-fg); cursor: default; }

/* ── menu, dialog, snackbar ────────────────────────────────────────────── */
.menu { position: fixed; z-index: 30; min-width: 200px; padding: 8px 0; border-radius: var(--r-lg); background: var(--md-surface-container);
  box-shadow: var(--shadow-2); animation: pop .2s var(--ease); }
.menu button { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 48px; padding: 0 16px; border: 0; background: none; cursor: pointer; text-align: left; font-size: var(--text); }
.menu button:hover { background: color-mix(in srgb, var(--md-on-surface) var(--state-hover), transparent); }
.menu .icon { color: var(--md-on-surface-variant); }
dialog { border: 0; padding: 24px; border-radius: var(--r-xl); background: var(--md-surface-container-high); color: var(--md-on-surface); width: min(560px, calc(100vw - 48px)); }
dialog { box-shadow: var(--shadow-3); }
dialog::backdrop { background: var(--scrim); }
dialog h2 { font-size: var(--text-title); line-height: var(--text-title-line); font-weight: 400; margin-bottom: 16px; }
dialog .field > span { --bgc: var(--md-surface-container-high); }
.card .field > span, .row .field > span, .opens .field > span { --bgc: var(--md-surface-container-low); }
dialog[open] { animation: pop .25s var(--ease); }
.snackbar {
  position: fixed; z-index: 40; left: calc(var(--rail-w) + var(--safe-left) + 16px); right: calc(var(--safe-right) + 16px);
  bottom: calc(var(--nav-h) + var(--safe-bottom) + var(--above, 0px) + 12px); max-width: 560px; margin: 0 auto;
  display: flex; align-items: center; gap: 8px; min-height: 48px; padding: 12px 16px; border-radius: var(--r-xs);
  background: var(--md-inverse-surface); color: var(--md-inverse-on-surface); font-size: var(--text); line-height: var(--text-line);
  box-shadow: var(--shadow-3); animation: rise .25s var(--ease);
}
.offline { /* app.js offline(): a line just under the bar, so it never covers the bar's buttons, while answers come from the saved copies */
  position: fixed; z-index: 41; top: calc(64px + var(--safe-top)); left: calc(var(--rail-w) + var(--safe-left)); right: var(--safe-right);
  display: flex; align-items: center; justify-content: center; min-height: 32px; padding: 0 16px;
  font-size: var(--text); line-height: var(--text-line); text-align: center; pointer-events: none;
  background: var(--md-surface-container-highest); color: var(--md-on-surface-variant); transition: top .2s var(--ease);
}
body:has(.bar.away) .offline { top: var(--safe-top); } /* Chat's bar slid away: the line follows it up */
/* "Updated — tap to refresh": a full 48px target, filled so it reads as a button. */
.embed .offline, body.bare .offline { top: var(--safe-top); } /* no bar to sit under */
.offline.tap { min-height: 48px; font-weight: 500; pointer-events: auto; cursor: pointer; background: var(--fill-tonal); color: var(--on-fill-tonal); }
@keyframes pop { from { opacity: 0; transform: scale(.94); } }
@keyframes rise { from { opacity: 0; transform: translateY(12px); } }

/* ── chat thread ───────────────────────────────────────────────────────── */
/* Chat is the densest screen (docs/v4/design-system.md § Type and density): the app-wide type scale, 8px between
   messages and 2px inside a group (index.html sameGroup: .joined is any but a group's last). */
/* Its bottom clears the composer (--above, its measured height) less the composer's 6px top padding, plus the 8px
   between messages: the last message sits as far above the field as messages sit apart. */
.thread { max-width: 760px; margin: 0 auto; padding: 8px 16px calc(var(--above, 80px) - 6px + var(--space-2)); overflow-x: clip; /* a swiped card never scrolls the page sideways */
  display: flex; flex-direction: column; gap: var(--space-2); font-size: var(--text); line-height: var(--text-line); }
.thread > .joined { margin-bottom: -6px; }
.day { align-self: center; margin-top: var(--space-1); padding: 2px 10px; border-radius: var(--r-full); background: var(--md-surface-container-high);
  font-size: var(--text-small); line-height: var(--text-small-line); font-weight: 500; letter-spacing: .5px; color: var(--md-on-surface-variant); }
.msg { max-width: min(85%, 560px); padding: 6px 12px; border-radius: var(--r-lg); white-space: pre-wrap; overflow-wrap: anywhere; }
.msg.me { align-self: flex-end; background: var(--fill-brand); color: var(--on-fill-brand); border-bottom-right-radius: var(--r-xs); }
.msg.aiko { max-width: 88%; align-self: flex-start; background: var(--chat-aiko); border-bottom-left-radius: var(--r-xs); }
.msg.joined { border-radius: var(--r-lg); } /* the tail only on a group's last */
.msg.pending { opacity: var(--emphasis-pending); }
/* Photos in Jason's bubble: one wide, or a row of squares; a tap opens the viewer. A photo-only bubble is just its photos. */
.photos { display: grid; gap: 4px; margin: -2px -8px 6px; }
.photos.n2 { grid-template-columns: 1fr 1fr; }
.photos.n3 { grid-template-columns: 1fr 1fr 1fr; }
.msg.only-photos { padding: 4px; }
.msg.only-photos .photos { margin: 0; }
.photo { display: block; width: 100%; border-radius: var(--r-md); background: var(--md-surface-container-highest); cursor: zoom-in; }
.photos.n1 .photo { width: min(280px, 60vw); max-height: 360px; object-fit: cover; }
.photos.n2 .photo, .photos.n3 .photo { aspect-ratio: 1; object-fit: cover; min-width: 0; }
.photos.charts { margin: 8px 0 0; }
.photos.charts .photo { width: min(340px, 72vw); max-height: none; aspect-ratio: auto; object-fit: contain; }
.photo.gone { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; min-height: 96px; padding: 8px; cursor: default;
  color: var(--md-on-surface-variant); font-size: var(--text-small); line-height: var(--text-small-line); white-space: normal; text-align: center; }
/* The viewer: one photo whole on the scrim; a tap anywhere closes it. */
dialog.viewer { padding: 0; width: auto; max-width: 100vw; max-height: 100vh; background: none; box-shadow: none; border-radius: 0; }
.viewer-close { display: block; padding: 0; border: 0; background: none; cursor: zoom-out; }
.viewer-close img { display: block; max-width: 100vw; max-height: 100vh; object-fit: contain; }
.aside { display: flex; align-items: flex-end; gap: 4px; max-width: 100%; }
/* The newest of Aiko's messages ends in 👍 👎 and ⋮, small, after its time (.signoff, index.html placeRate), on the row it
   ends on (its buttons, its last fold line) or a row of their own. Each such row centres its parts on one line. */
.rate { display: flex; flex: none; margin-right: -8px; isolation: isolate; } /* the ⋮ glyph lines up with the words' edge */
.rate .icon-btn { width: 32px; height: 32px; }
.rate .icon-btn::after { z-index: -1; height: 100%; } /* edge to edge: each one's own box stays over its neighbour's wider tap area; wider only, never over the words above */
.rate .icon { font-size: var(--icon-m); }
.signoff { clear: both; display: flex; flex: none; justify-content: flex-end; align-items: center; gap: 4px; margin-left: auto; } /* its time, then the thumbs: one piece */
/* The picked thumb: filled, in the theme's primary colour (never an emoji). */
.rate .icon-btn[aria-pressed="true"] { --fg: var(--md-primary); }

/* A reply's quote: a bar in the replied message's colour, its name and first line. Tapping it jumps there. */
.quote-ref { display: block; width: 100%; text-align: left; font: inherit; color: inherit; cursor: pointer; border: 0;
  margin: 0 0 6px; padding: 6px 10px; border-radius: var(--r-sm); border-left: 4px solid var(--k-fg);
  background: color-mix(in srgb, var(--k-bg) var(--tint-quote), transparent); }
.quote-ref b { display: flex; align-items: center; gap: 4px; font-size: var(--text-small); line-height: var(--text-small-line); font-weight: 500; color: var(--k-fg); }
.quote-ref b .icon { font-size: var(--icon-s); }
.quote-ref span { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; font-size: var(--text-small); line-height: var(--text-small-line); white-space: normal; }
.msg.me .quote-ref { background: var(--tint-quote-on-brand); border-left-color: var(--on-fill-brand); }
.msg.me .quote-ref b { color: var(--on-fill-brand); }
.flash { animation: flash 1.4s var(--ease); }
@keyframes flash { 0%, 40% { box-shadow: 0 0 0 3px var(--md-primary); } 100% { box-shadow: 0 0 0 3px transparent; } }
.time, .stamp { font-size: var(--text-small); line-height: var(--text-small-line); font-weight: 400; letter-spacing: .3px; color: var(--md-on-surface-variant); }
.time { margin: 2px 8px 6px; }
/* A chat line's time, inside the bubble after its last words: floated, so it shares their line when there is room (index.html stamp). */
.stamp { float: right; display: inline-flex; align-items: center; gap: 2px; margin: 6px -4px -4px 10px; white-space: nowrap; }
.acts > .stamp, .signoff > .stamp, .fold-line > summary > .stamp { float: none; flex: none; margin: 0 0 0 auto; } /* at the end of the row a message ends on (index.html endOf) */
.stamp .icon, .receipt .stamp .icon { font-size: var(--icon-s); margin: 0; color: var(--md-primary); }
.msg.me .stamp, .msg.me .stamp .icon { color: inherit; opacity: var(--emphasis-pending); }
.msg a { color: var(--md-primary); }
.msg.me a { color: inherit; }
/* Aiko's messages move with a swipe-to-reply and hold for a menu (index.html gestures): a vertical drag still scrolls,
   and on a touch screen a hold opens the menu, not text selection (Copy text is in it). */
.msg.aiko, .pro { --md-on-surface-variant: var(--on-chat-aiko-variant); --md-outline-variant: var(--chat-aiko-outline); position: relative; touch-action: pan-y; transition: left .2s var(--ease); }
.msg.aiko.dragging, .pro.dragging { transition: none; }
@media (pointer: coarse) { .msg.aiko, .pro { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; } }
.new { animation: rise .35s var(--ease); }

/* A message code wrote (an approval, an alert, a web task: index.html isCard): a full-width card in its kind's colour,
   the kind's icon leading its first line (index.html lead), its time after its last words, and its buttons. Aiko's own
   messages are bubbles, led by the same icon. */
.pro { width: 100%; align-self: flex-start; padding: var(--space-2) var(--space-3); border-radius: var(--r-md); background: var(--chat-aiko); }
.kind-ic { font-size: var(--icon-s); vertical-align: -3px; margin-right: 6px; color: var(--k-fg); font-variation-settings: 'FILL' 1; }
.row > .kind { width: 40px; height: 40px; display: grid; place-items: center; border-radius: var(--r-md); background: var(--k-bg); color: var(--k-fg); flex: none; }
.row > .kind .icon { font-variation-settings: 'FILL' 1; }
.pro .text { overflow-wrap: anywhere; }
.k-primary { --k-bg: var(--md-primary-container); --k-fg: var(--md-on-primary-container); }
.k-secondary { --k-bg: var(--md-secondary-container); --k-fg: var(--md-on-secondary-container); }
.k-tertiary { --k-bg: var(--md-tertiary-container); --k-fg: var(--md-on-tertiary-container); }
.k-error { --k-bg: var(--md-error-container); --k-fg: var(--md-on-error-container); }
.pro.k-error { background: var(--tint-error-card); }
/* A message's items: one compact row each (index.html itemRow, a .row.dense), darker than the bubble, its ends less round. */
.msg .items { position: relative; display: flex; flex-direction: column; gap: 2px; margin-top: var(--space-2); white-space: normal; } /* over a fold's tap area */
.msg .items .row { background: var(--md-surface-container); }
.msg .items .row:first-child { border-top-left-radius: var(--r-sm); border-top-right-radius: var(--r-sm); }
.msg .items .row:last-child { border-bottom-left-radius: var(--r-sm); border-bottom-right-radius: var(--r-sm); }
.why { display: flex; gap: 8px; margin-top: 8px; color: var(--md-on-surface-variant); font-size: var(--text); line-height: var(--text-line); }
.why .icon { font-size: var(--icon-s); color: var(--md-tertiary); margin-top: 1px; }
.why:empty { display: none; }
.quote { margin-top: 4px; padding: 12px 16px; border-radius: var(--r-lg); background: var(--md-surface-container-highest); white-space: pre-wrap; overflow-wrap: anywhere; }
.receipts { margin-top: var(--space-1); display: flex; flex-direction: column; gap: 2px; }
.receipt { display: flex; gap: 6px; font-size: var(--text-small); line-height: var(--text-small-line); color: var(--md-on-surface-variant); }
.receipt > span { flex: 1; min-width: 0; } /* the full width, so the time floats onto the last line when it fits */
.receipt .icon { font-size: var(--icon-s); margin-top: 1px; color: var(--md-primary); font-variation-settings: 'FILL' 1; }
/* Several rows (a message's receipts or items) as one quiet line, closed until tapped (index.html foldLine). */
/* Its summary is a real 36px box, so the tap area never reaches over the words above; last (and shut) in a card or bubble it
   runs into the padding below, which is empty. */
.fold-line > summary { display: flex; align-items: center; gap: 6px; min-height: 36px; padding: 0; font-size: var(--text-small); line-height: var(--text-small-line); font-weight: 400; color: var(--md-on-surface-variant); }
.pro > .fold-line:not([open]):last-child { margin-bottom: -8px; }
.msg > .fold-line:not([open]):last-child { margin-bottom: -6px; }
.fold-line > .items { margin-top: 0; }
.fold-line > summary > .icon { font-size: var(--icon-s); color: var(--md-primary); font-variation-settings: 'FILL' 1; }
.fold-line > summary > span:first-of-type { flex: 1; min-width: 0; } /* its words; a time or thumbs after them keep their size */
.fold-line .chev { font-size: var(--icon-s); vertical-align: -3px; transition: transform .2s var(--ease); }
.fold-line[open] .chev { transform: rotate(90deg); }
/* Words as written (an approval's), and a long one folded to six lines until tapped (index.html plain). */
.plain { white-space: pre-wrap; overflow-wrap: anywhere; }
.long > summary { display: block; min-height: 0; font: inherit; }
.long:not([open]) .plain { display: -webkit-box; -webkit-line-clamp: 6; -webkit-box-orient: vertical; overflow: hidden; }
.long .hint { display: block; margin-top: 2px; font-size: var(--text-small); line-height: var(--text-small-line); font-weight: 500; color: var(--md-primary); }
.long[open] .hint { display: none; }
/* Aiko's words in Chat as Markdown (app.js markdown: her replies, cards' words, a web task's result), and a web task card's folded details with the final screenshot.
   A heading reads as a bold line: chat has no sections. */
.result { overflow-wrap: anywhere; white-space: normal; }
.pro .result:not(.text) { margin-top: var(--space-2); }
.result p, .result h1, .result h2, .result h3 { margin: var(--space-2) 0; }
.result h1, .result h2, .result h3 { font-size: inherit; line-height: inherit; font-weight: 600; }
.result ul, .result ol { margin: var(--space-1) 0; padding-left: var(--space-6); }
.result ul { list-style: disc; }
.result li { margin: var(--space-1) 0; }
.result b { font-weight: 600; }
.result > :first-child { margin-top: 0; }
.result > :last-child, .result > ul > li:last-child, .result > ol > li:last-child { margin-bottom: 0; }
.pro .photos.final-shot { margin-top: var(--space-2); }
.pro .photos.final-shot .photo { width: min(220px, 50vw); border: 1px solid var(--md-outline-variant); }
.pro details.more > summary { gap: var(--space-1); min-height: 36px; list-style: none; font-size: var(--text-small); color: var(--md-on-surface-variant); } /* 36px: clear of the words above and the buttons below */
.pro details.more > summary .icon { font-size: var(--icon-s); }
.pro details.more > summary::-webkit-details-marker { display: none; }
.pro details.more > summary .icon { transition: transform .2s var(--ease); }
.pro details.more[open] > summary .icon { transform: rotate(180deg); }
.msg.me .receipt, .msg.me .receipt .icon { color: inherit; }
/* A decided approval (index.html decidedLine): one quiet line in place of its card; Aiko's own message says it is done. */
.pro.decided { padding: 0 4px; background: none; }
.state { display: inline-flex; align-items: center; gap: 6px; margin-top: 12px; font-size: var(--text); font-weight: 500; color: var(--md-on-surface-variant); }
.state .icon { font-size: var(--icon-m); color: var(--md-primary); font-variation-settings: 'FILL' 1; }

/* Aiko at work: her own bubble with three dots and what she is doing now (index.html showProgress). */
.msg.typing { display: flex; align-items: center; gap: 12px; white-space: normal; color: var(--md-on-surface-variant); }
.dots { display: inline-flex; gap: 4px; flex: none; }
.dots i { width: 8px; height: 8px; border-radius: 50%; background: var(--md-primary); animation: bounce 1.2s var(--ease) infinite; }
.dots i:nth-child(2) { animation-delay: .15s; }
.dots i:nth-child(3) { animation-delay: .3s; }
@keyframes bounce { 0%, 60%, 100% { transform: none; opacity: .4; } 30% { transform: translateY(-4px); opacity: 1; } }
.stage.swap { animation: swap .3s var(--ease); }
@keyframes swap { from { opacity: 0; transform: translateY(4px); } }
/* Still, the dots read as a pause, not a stall: a fixed fade from left to right. */
@media (prefers-reduced-motion: reduce) {
  .dots i { opacity: .8; }
  .dots i:nth-child(2) { opacity: .55; }
  .dots i:nth-child(3) { opacity: .3; }
}

/* Composer: a pill field with mic and send, above the nav bar. */
.composer {
  position: fixed; z-index: 8; left: calc(var(--rail-w) + var(--safe-left)); right: var(--safe-right);
  bottom: calc(var(--nav-h) + var(--safe-bottom)); padding: 6px 12px 10px;
  background: linear-gradient(transparent, var(--md-surface) 8px);
}
.composer .replying { max-width: 760px; margin: 0 auto 8px; display: flex; align-items: center; gap: 4px; padding: 4px 4px 4px 8px;
  border-radius: var(--r-lg); background: var(--md-surface-container-high); }
.composer .replying .quote-ref { margin: 0; flex: 1; min-width: 0; }
/* Photos waiting to send: 64dp thumbnails above the field, each with × in its corner. */
.composer .attached { max-width: 760px; margin: 8px auto 8px; /* room above for each thumb's ×, which sits 8px out */ display: flex; gap: 8px; }
.composer .thumb { position: relative; width: 64px; height: 64px; flex: none; }
.composer .thumb img { width: 100%; height: 100%; object-fit: cover; border-radius: var(--r-md); }
.composer .thumb .remove { position: absolute; top: -8px; right: -8px; width: 28px; height: 28px; --bg: var(--md-surface-container-highest); --fg: var(--md-on-surface); }
.composer .thumb .remove .icon { font-size: var(--icon-s); }
.composer .inner { max-width: 760px; margin: 0 auto; display: flex; align-items: flex-end; gap: 8px; }
/* The field: 56px on one line, so --r-xl (28px) is a pill there and a fixed large radius as it grows. Its 40px
   buttons sit 8px in from every edge and stay at the bottom, centred on the last line of text, at any height. */
.composer .pillbox { flex: 1; display: flex; align-items: flex-end; min-height: 56px; border-radius: var(--r-xl); background: var(--md-surface-container-high); padding: 8px; }
.composer .pillbox .icon-btn { width: 40px; height: 40px; }
.composer textarea { flex: 1; min-width: 0; border: 0; outline: 0; background: none; resize: none; padding: 9px 4px; max-height: 128px; font-size: var(--text); line-height: var(--text-line); }
.composer textarea::placeholder { color: var(--md-on-surface-variant); }
.composer .send { border-radius: var(--r-full); } /* in the field, where the mic is while there is nothing to send */
.composer.recording .pillbox { background: var(--md-error-container); color: var(--md-on-error-container); }
.composer.recording .rec { --bg: var(--fill-danger); --fg: var(--on-fill-danger); animation: pulse 1.2s ease-in-out infinite; }
@keyframes pulse { 50% { box-shadow: 0 0 0 8px var(--tint-recording); } }

/* The Log beside the chat (index.html adds it in a browser, never in the app). The one breakpoint:
   index.html loads the Log only while .log-panel shows. */
.log-toggle, .log-panel { display: none; }
@media (min-width: 1100px) {
  .log-toggle { display: inline-flex; }
  .with-log { --panel-w: 400px; padding-right: calc(var(--safe-right) + var(--panel-w)); }
  .with-log .composer { right: calc(var(--safe-right) + var(--panel-w)); }
  .with-log .snackbar { right: calc(var(--safe-right) + var(--panel-w) + 16px); }
  .with-log .log-panel { display: block; position: fixed; top: 0; right: 0; width: var(--panel-w); height: 100dvh; border-left: 1px solid var(--md-outline-variant); }
}
.log-panel iframe { display: block; width: 100%; height: 100%; border: 0; }
.log-toggle[aria-pressed="true"] { --fg: var(--md-primary); }
/* log.html?embed=1, inside that panel: no top bar, no nav. */
.embed { --nav-h: 0px; --rail-w: 0px; }
.embed .bar { display: none; }

/* Review: the week's numbers, one compact row each (this week's at the end, its trend beside it), and the records under
   a proposal or failing criterion. */
.row.dense > .num { display: flex; align-items: center; gap: 2px; margin-right: var(--space-4); font-size: var(--text-title); line-height: var(--text-title-line); font-weight: 500; }
.num .icon { font-size: var(--icon-m); color: var(--md-on-surface-variant); }
.num .better { color: var(--md-primary); }
.num .worse { color: var(--md-error); }
.records { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
.record { padding: 8px 12px; border-radius: var(--r-md); background: var(--md-surface-container-highest); overflow-wrap: anywhere; }
.clamp { display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
.row .text { white-space: pre-wrap; }

/* About this build (More): M3 label-small, quiet; a tap copies it. */
.build { position: relative; display: block; margin: 24px auto 0; padding: 8px 12px; border: 0; border-radius: var(--r-sm); background: none; cursor: pointer;
  font-size: var(--text-small); line-height: var(--text-small-line); font-weight: 500; letter-spacing: .5px; color: var(--md-on-surface-variant); text-align: center; white-space: pre-line; }
.build:empty { display: none; } /* until /api/version answers */
.build:hover { background: color-mix(in srgb, var(--md-on-surface) var(--state-hover), transparent); }

/* Login: the page draws its own edges. */
body.bare { padding: 0; }
.login { min-height: 100dvh; display: grid; place-items: center; padding: 24px; text-align: center; }
.login .mark { width: 72px; height: 72px; margin: 0 auto 24px; }
.login .card { padding: 40px 32px; width: min(400px, 100%); background: var(--md-surface-container-low); }
.login .meta { margin: 8px 0 32px; }

/* Outcome icons (Log, Schedule, Review, a decided approval): the status tokens. Here, after the rows and receipts, so
   they win over a row's lead icon colour and a receipt's. */
.icon.status-ok { color: var(--status-ok); }
.icon.status-muted { color: var(--status-muted); }
.icon.status-bad { color: var(--status-bad); }

/* ── screen components (one screen each today, here so any screen can reuse them) ── */
/* A web task's page (scripts/browse-trial.js --web): the card waiting on Jason, and a page screenshot. */
.card.ask { box-shadow: inset 0 0 0 2px var(--md-primary); }
.shot { display: block; width: 100%; height: auto; margin-top: var(--space-3); border-radius: var(--r-md); border: 1px solid var(--md-outline-variant); }
/* A code block (a prompt, a skill's example) and a collapsible heading (a prompt's part, a skill's front matter). */
pre.prompt { margin: var(--space-2) 0 0; white-space: pre-wrap; overflow-wrap: anywhere; font: var(--text-small)/var(--text-small-line) var(--font-mono); }
details > summary { min-height: 48px; display: flex; align-items: center; cursor: pointer; font-size: var(--text); font-weight: 500; }

/* Memory: a person is one row that opens in place (.opens): who they are (other names, emails, dates and flags),
   then their notes, if any (the facts, as a nested list one container tone up), then + Date, + Note, Edit and Delete. */
.avatar { width: 40px; height: 40px; border-radius: var(--r-full); display: grid; place-items: center; flex: none;
  background: var(--md-secondary-container); color: var(--md-on-secondary-container); font-size: var(--text); font-weight: 500; }
.person .details, .person-form { display: flex; flex-direction: column; gap: var(--space-2); }
.person .details:empty { display: none; }
.person .chip { min-height: 28px; font-size: var(--text-small); } /* small, so two dates share a line on a phone */
.person .chip .icon { font-size: var(--icon-s); }
.person-form .field, .note-form .field { margin: var(--space-2) 0 0; }
.person-form .acts, .note-form .acts { margin-top: var(--space-2); }
.note-form { display: flex; flex-direction: column; gap: var(--space-2); }
.detail { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text); line-height: var(--text-line); color: var(--md-on-surface-variant); }
.detail .icon { font-size: var(--icon-m); }
.chips { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.switch-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); min-height: 48px; font-size: var(--text); }
.switch-row small { display: block; font-size: var(--text-small); line-height: var(--text-small-line); }
.notes { margin-top: var(--space-3); padding-top: var(--space-3); border-top: 1px solid var(--md-outline-variant); }
.notes:empty { display: none; }
.notes > .sub { margin: 0 0 var(--space-2); }
.notes .row { background: var(--md-surface-container); }
.notes .row .field > span { --bgc: var(--md-surface-container); }
.person .foot { margin: var(--space-3) -8px 0 0; }
.spot .foot { margin: var(--space-1) 0 0; } /* inside a row's padding, not a bubble's edge */
.person .details:empty + .notes:empty + .foot { margin-top: 0; }

/* Schedule: a routine's compact row (schedule.html entryRow). Its words are the link to its page; its status is one
   flowing small line, the last run led by its outcome's icon; its editor opens under the row, full width. */
.row.dense.routine { flex-wrap: wrap; }
.routine > a.main { color: inherit; text-decoration: none; }
.routine > .switch { margin: 0 var(--space-1) 0 var(--space-4); } /* a clear gap: a near-miss on the switch never opens the page */
.routine > .edit { flex-basis: 100%; padding: 0 var(--space-3) var(--space-3) 0; }
.routine > .edit:empty { display: none; }
.row.dense .meta.lines { display: block; }
.lines .icon { font-size: var(--icon-s); vertical-align: -3px; margin-right: 2px; }
/* The hour picker: 24 toggle chips in rows of four, wide enough to tap on a 360px phone. */
.hour-pick { margin-top: var(--space-3); }
.hour-pick .label-m { color: var(--md-on-surface-variant); }
.hours { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-2); margin-top: var(--space-2); }
.hours .chip { padding: 0; }
.chip[aria-pressed="true"] { --bg: var(--fill-tonal); --fg: var(--on-fill-tonal); box-shadow: none; }
/* Hours (Schedule; stored as the strip): 24 hour chips, each Off or On; a tap toggles it. The briefing and wrap hours
   are On, with their own icon. */
.chip.lvl { box-shadow: none; justify-content: center; gap: 2px; }
.chip.lvl-on { --bg: var(--level-on-bg); --fg: var(--level-on-fg); }
.chip.lvl-off { --bg: var(--level-off-bg); --fg: var(--level-off-fg); }
.chip.lvl .icon { font-size: var(--icon-s); color: inherit; }
.legend { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-top: var(--space-2); }
.legend .badge { padding: 2px 6px; } /* the four on one line on a 360px phone */
.legend .badge.lvl-on { background: var(--level-on-bg); color: var(--level-on-fg); }
.legend .badge.lvl-off { background: var(--level-off-bg); color: var(--level-off-fg); }

/* Skills: tag rows, and a skill's text rendered from Markdown. */
.tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: var(--space-2); }
.tags .sub { width: 100%; }
.md { margin-top: var(--space-2); overflow-wrap: anywhere; }
.md h1 { font-size: var(--text-title); line-height: var(--text-title-line); font-weight: 400; margin: var(--space-2) 0 var(--space-3); }
.md h2 { font-size: var(--text); line-height: var(--text-line); font-weight: 500; margin: 20px 0 var(--space-2); color: var(--md-primary); }
.md h3 { font-size: var(--text); line-height: var(--text-line); font-weight: 500; margin: var(--space-4) 0 var(--space-1); }
.md p { margin: var(--space-2) 0; }
.md ol, .md ul { margin: var(--space-2) 0; padding-left: var(--space-6); }
.md ul { list-style: disc; }
.md li { margin: var(--space-1) 0; }
.md code, .result code { font-family: var(--font-mono); font-size: var(--text-small); padding: 1px var(--space-1); border-radius: var(--r-xs); background: var(--md-surface-container-highest); }
.md pre, .result pre { overflow-x: auto; padding: var(--space-3) var(--space-4); border-radius: var(--r-md); background: var(--md-surface-container-highest); }
.md pre code, .result pre code { padding: 0; background: none; }
.msg.aiko .result code, .msg.aiko .result pre, .pro .result code, .pro .result pre { background: var(--md-surface-container); } /* Aiko's surfaces are lighter than the highest container: code sits darker */
/* Skills: scrolled to (?name=, or Read and Change on a version), clear of the sticky top bar. */
.opens.skill, .opens.skill .card.outlined { scroll-margin-top: calc(64px + var(--safe-top) + var(--space-2)); }
details.front { margin-top: var(--space-3); }
details.front summary { color: var(--md-on-surface-variant); }
/* A skill's line diff (Skills screen): removed lines, then the ones that replace them. */
.diff { margin: 0; overflow-x: auto; font-family: var(--font-mono); font-size: var(--text-small); line-height: var(--text-small-line); white-space: pre-wrap; overflow-wrap: anywhere; }
.diff span { display: block; padding: 0 var(--space-2); border-radius: var(--r-xs); }
.diff .add { background: var(--md-primary-container); color: var(--md-on-primary-container); }
.diff .del { background: var(--md-error-container); color: var(--md-on-error-container); }
.diff .same { color: var(--md-on-surface-variant); }
.field textarea.code { font-family: var(--font-mono); } /* a field's 16px: a phone zooms into a smaller one */

/* Page transitions between screens, off for reduced motion. */
@media (prefers-reduced-motion: no-preference) { @view-transition { navigation: auto; } }
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation: none !important; transition: none !important; } }
