/*
 * Watchless look: C · Studio (the human's choice, 2026-10-22; draft
 * pod-docs/design-drafts/dark-look-directions.html). Black with soft grey
 * tiles and no borders, one violet accent, Lexend. Phone-first and round.
 *
 * The only file with color and font values. Page stylesheets use these
 * custom properties and never write a hex, rgb()/hsl() or font family.
 * Fonts are self-hosted (SIL Open Font License, see fonts/OFL-Lexend.txt).
 *
 * Two themes. Dark is the default (:root). Light comes from the theme
 * switch (data-theme="light" on <html>, set by the server from the
 * watchless_theme cookie) or, with System picked, from the OS. The two
 * light blocks below must stay the same (tests/test_look.py checks it).
 * Black and white do most of the work: primary buttons are the inverse
 * (white on black, black on white). Violet is for the check, links, the
 * focus ring, "The point", the brand dot and the selected state.
 * pod-docs/design.md is the style guide: every rule there matches this file.
 */

:root {
  /* Palette: dark */
  --bg: #000000;            /* page background */
  --surface: #1C1C1E;       /* cards, panels, the tab bar: grey tiles */
  --field-tile: #2C2C2E;    /* a field's fill inside a tile: apart from the tile and from an inset notice (--bg) */
  --field-page: #2C2C2E;    /* a field's fill on the page: apart from the page and from a notice tile (--surface) */
  --text: #FFFFFF;
  --muted: #A1A1A6;         /* secondary text */
  --soft: #8E8E93;          /* quieter text: a read card's channel and time */
  --divider: #38383A;       /* hairlines between rows */
  --line-strong: #3A3A3C;   /* faint edges: secondary buttons, the menu, quiet dots */
  --check-line: #7C7C80;    /* the unread check's ring: 3:1 on every surface */
  --accent: #A58BFF;        /* violet: the check, links, focus, The point, the brand dot */
  --accent-hover: #B9A5FF;
  --accent-press: #CBBDFF;
  --accent-text: #B4A0FF;   /* violet for links and text (4.5:1 on --press too) */
  --on-accent: #000000;     /* the tick on a done check */
  --inv: #FFFFFF;           /* primary buttons: the inverse of the page */
  --on-inv: #000000;
  --inv-hover: #E5E5EA;
  --inv-press: #D1D1D6;
  --focus: #A58BFF;         /* focus ring */
  --hover: #2C2C2E;         /* secondary control hover */
  --press: #3A3A3C;         /* secondary control press */
  --ok: #30D158;            /* done: OK and Used dots, done steps */
  --warn: #FFB340;          /* run warnings, warn dots */
  --error: #FF6961;
  --danger: #FF6961;        /* danger button */
  --on-danger: #000000;
  --danger-hover: #FF8A84;
  --danger-press: #FFA6A1;
  --danger-soft: #2E1514;   /* the error notice's fill; a quiet red button's hover fill */
  --scrim: rgb(0 0 0 / .7); /* behind a dialog */
  /* Channel colors: each channel keeps one slot (web/theme.py), drawn in
     each theme's own shade, 4.5:1 on --bg, --surface and --hover. */
  --ch-1: #5AC8F5;          /* cyan */
  --ch-2: #E57EF1;          /* orchid: 40 degrees or more of hue from the accent, the status colors and every other slot */
  --ch-3: #FF7EB6;          /* pink */
  --ch-4: #FFC247;          /* amber */
  --ch-5: #7DAEFF;          /* blue */
  --ch-6: #9BD45F;          /* olive */
  --ch-7: #FF9466;          /* rust */

  /* Type */
  --display: "Lexend", system-ui, sans-serif;
  --body: "Lexend", system-ui, sans-serif;
  --dw: 600;                /* the display weight: Lexend is loaded at 400 and 600 */
  /* Even pixels only (the human's choice, 2026-10-21). */
  --fs-display: 24px;       /* page headline */
  --fs-heading: 20px;       /* section and day heading */
  --fs-title: 16px;         /* video title, card heading */
  --fs-summary: 16px;       /* summaries and other long reading */
  --fs-body: 14px;          /* buttons, labels, previews, most of the app */
  --fs-caption: 12px;       /* captions and meta (channel and time) */
  --fs-input: 16px;         /* form fields: iPhone zooms in on anything smaller */
  /* Line heights: even pixels, so every line box is too (the human's choice,
     2026-10-23). */
  --lh-caption: 16px;       /* 12 px captions and meta */
  --lh-body: 20px;          /* 14 px body text, buttons, labels */
  --lh-label: 20px;         /* field labels: a field is 20 + 8 + 44 = 72 px */
  --lh-title: 24px;         /* 16 px video titles and panel titles */
  --lh-summary: 26px;       /* 16 px summaries and other long reading */
  --lh-heading: 28px;       /* 20 px section and day headings */
  --lh-display: 32px;       /* the 24 px page heading */

  /* Space: a 4 px grid (the human's choice, 2026-10-21). Page stylesheets
     space things with these tokens only, never a raw length. */
  --s0: 2px;                /* small nudges inside one line only */
  --s1: 4px;
  --s2: 8px;
  --s3: 12px;
  --s4: 16px;
  --s5: 24px;
  --s6: 32px;
  --s7: 48px;
  --s8: 64px;

  /* Space roles */
  --gutter: var(--s4);      /* page side padding; the header uses it too */
  --pad-panel: var(--s5);   /* panels and dialogs; 16 px on phones */
  --pad-note: var(--s3) var(--s4); /* notices */
  --list-gap: var(--s2);    /* between feed cards */
  --row-py: var(--s3);      /* rows in a divided list */
  --stack: var(--s4);       /* between panels and notices */
  --head-gap: var(--s5);    /* page heading block to content */
  --section: var(--s6);     /* between page sections and day sections */
  --btn-h: 36px;            /* a button's drawn height (the human's choice, 2026-10-23); the tap area stays --tap */
  --btn-px: 16px;           /* button side padding */

  /* Shape */
  --r: 14px;                /* cards and panels */
  --rbtn: var(--r);         /* buttons and segmented controls: the card radius, no pills (the human's choice, 2026-10-22) */
  --rpill: 999px;           /* badges and labels: fully round */
  --rinput: 8px;            /* menu items and the link box; fields use --rbtn */
  --rbox: 4px;              /* code and small boxes */
  --bw: 1px;
  --bw-strong: 2px;         /* the check ring, step rings */
  --bar: 4px;               /* progress and tone marks */
  --ring: 2px;              /* focus ring width */
  --dot: 8px;               /* status dots in lists and tables */
  --dot-lg: 10px;           /* the dot that leads a notice or a row; the brand dot */
  --avatar: 32px;
  --page-max: 760px;        /* the one centered column; the header lines up with it */
  --measure: 65ch;          /* longest reading line */
  --form-max: 560px;        /* form fields and the text around them */
  --dialog-max: 440px;      /* dialogs, confirm pages, the sign-in card */
  --control-h: 44px;
  --check: 24px;            /* the round mark-read button, as drawn */
  --tap: 44px;              /* the least tap target, for controls drawn smaller */
  --tabbar-h: 60px;         /* the phone tab bar */

  color-scheme: dark;
}

/* Light, picked in the theme switch. */
:root[data-theme="light"] {
  --bg: #F2F2F2;
  --surface: #FFFFFF;
  --field-tile: #E0E0E5;
  --field-page: #E0E0E5;
  --text: #000000;
  --muted: #5C5C60;
  --soft: #6C6C70;
  --divider: #E5E5EA;
  --line-strong: #C7C7CC;
  --check-line: #7C7C80;
  --accent: #5B3FD9;
  --accent-hover: #4A30C2;
  --accent-press: #3C26A6;
  --accent-text: #5B3FD9;
  --on-accent: #FFFFFF;
  --inv: #000000;
  --on-inv: #FFFFFF;
  --inv-hover: #2C2C2E;
  --inv-press: #3A3A3C;
  --focus: #5B3FD9;
  --hover: #E9E9EB;
  --press: #DEDEE2;
  --ok: #248A3D;
  --warn: #8F5300;
  --error: #C4291C;
  --danger: #C4291C;
  --on-danger: #FFFFFF;
  --danger-hover: #A82317;
  --danger-press: #8C1D13;
  --danger-soft: #FCEBEA;
  --scrim: rgb(0 0 0 / .4);
  --ch-1: #0B6680;
  --ch-2: #9412A5;
  --ch-3: #BE185D;
  --ch-4: #8A5600;
  --ch-5: #1D4ED8;
  --ch-6: #3F6A0A;
  --ch-7: #9A3412;
  color-scheme: light;
}

/* System: light when the OS asks for it, unless Dark was picked. The same
   block as above. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --bg: #F2F2F2;
    --surface: #FFFFFF;
    --field-tile: #E0E0E5;
    --field-page: #E0E0E5;
    --text: #000000;
    --muted: #5C5C60;
    --soft: #6C6C70;
    --divider: #E5E5EA;
    --line-strong: #C7C7CC;
    --check-line: #7C7C80;
    --accent: #5B3FD9;
    --accent-hover: #4A30C2;
    --accent-press: #3C26A6;
    --accent-text: #5B3FD9;
    --on-accent: #FFFFFF;
    --inv: #000000;
    --on-inv: #FFFFFF;
    --inv-hover: #2C2C2E;
    --inv-press: #3A3A3C;
    --focus: #5B3FD9;
    --hover: #E9E9EB;
    --press: #DEDEE2;
    --ok: #248A3D;
    --warn: #8F5300;
    --error: #C4291C;
    --danger: #C4291C;
    --on-danger: #FFFFFF;
    --danger-hover: #A82317;
    --danger-press: #8C1D13;
    --danger-soft: #FCEBEA;
    --scrim: rgb(0 0 0 / .4);
    --ch-1: #0B6680;
    --ch-2: #9412A5;
    --ch-3: #BE185D;
    --ch-4: #8A5600;
    --ch-5: #1D4ED8;
    --ch-6: #3F6A0A;
    --ch-7: #9A3412;
    color-scheme: light;
  }
}

@font-face {
  font-family: "Lexend";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/lexend-vietnamese-400-normal.woff2") format("woff2");
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: "Lexend";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/lexend-latin-ext-400-normal.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: "Lexend";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/lexend-latin-400-normal.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+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Lexend";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/static/fonts/lexend-vietnamese-600-normal.woff2") format("woff2");
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: "Lexend";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/static/fonts/lexend-latin-ext-600-normal.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: "Lexend";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/static/fonts/lexend-latin-600-normal.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+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* --- Base ------------------------------------------------------------------ */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; background: var(--bg); }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  overflow-wrap: anywhere;
  --field-bg: var(--field-page); /* a field on the page; .panel and .menu set the tile fill */
}

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: var(--dw);
  letter-spacing: -0.01em;
  margin: 0 0 var(--s3);
  overflow-wrap: break-word;
  text-wrap: balance;       /* no lone last word */
}
h1 { font-size: var(--fs-display); line-height: var(--lh-display); }
h2 { font-size: var(--fs-heading); line-height: var(--lh-heading); }
h3 { font-size: var(--fs-title); line-height: var(--lh-title); }
h4 { font-size: var(--fs-body); line-height: var(--lh-body); }

p { margin: 0 0 var(--s3); }

a { color: var(--accent-text); text-underline-offset: 3px; }
a:hover { text-decoration-thickness: 2px; }

code {
  font-family: var(--body);
  font-weight: 600;
  background: var(--hover);
  border-radius: var(--rbox);
  padding: 0 var(--s1);
}

:focus { outline: none; }
:focus-visible {
  outline: var(--ring) solid var(--focus);
  outline-offset: 2px;
}

.muted { color: var(--muted); }
.summary { font-size: var(--fs-summary); line-height: var(--lh-summary); max-width: var(--measure); }
.caption { font-size: var(--fs-caption); line-height: var(--lh-caption); color: var(--muted); }
.error-text { color: var(--error); }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: calc(-1 * var(--bw)); padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --- Shell: header, menu, account ------------------------------------------ */

.skip-link {
  position: absolute;
  left: max(var(--gutter), calc((100% - var(--page-max)) / 2 + var(--gutter))); /* in the page column */
  top: calc(-2 * var(--s8)); /* off screen until focused */
  background: var(--inv);
  color: var(--on-inv);
  display: inline-flex;
  align-items: center;
  min-height: var(--control-h);
  padding: 0 var(--s4);
  border-radius: var(--rbtn);
  font-weight: 600;
  z-index: 30;
}
.skip-link:focus-visible { top: var(--s2); }

/* The header: no line under it; 60 px tall, on the grid. */
.site-header { background: var(--bg); }
/* The header's row lines up with the page column at every width: the brand
   starts where the page's text starts, and the avatar ends where it ends. */
.site-header .bar {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: var(--s2) var(--gutter);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s2) var(--s5);
}
.brand {
  font-family: var(--display);
  font-weight: var(--dw);
  font-size: var(--fs-heading);
  line-height: var(--lh-heading);
  letter-spacing: -0.01em;
  color: var(--text);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  min-height: var(--control-h);
  flex: none;
}
/* The brand mark: one violet dot. */
.brand-dot { flex: none; width: var(--dot-lg); height: var(--dot-lg); border-radius: 50%; background: var(--accent); }

.tabs { flex: 1 1 auto; }
.nav { display: flex; gap: var(--s1); margin: 0; padding: 0; list-style: none; }
.nav a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--control-h);
  padding: 0 var(--s4);
  border-radius: var(--rbtn);
  color: var(--muted);
  text-decoration: none;
  font-weight: 600;
}
.nav a:hover { color: var(--text); background: var(--hover); }
.nav a:active { background: var(--press); }
.nav a[aria-current="page"] { color: var(--accent-text); background: var(--hover); }

.account {
  display: flex;
  align-items: center;
  margin-left: auto;
  min-width: 0;
}
/* The avatar menu: a <details> (account-menu.js adds Escape and outside click). */
.account-menu { position: relative; min-width: 0; }
/* The avatar sits the same distance from the button's edge on top, bottom
   and left; the caret's side is 8 px, so the button's fill ends on the page
   column's edge, flush with the menu under it. No ring on the avatar: the
   menu marks the current page, and keyboard focus gets the focus ring. */
.account-btn {
  display: flex;
  align-items: center;
  gap: var(--s2);
  min-width: 0;
  min-height: var(--control-h);
  padding: 0 var(--s2) 0 calc((var(--control-h) - var(--avatar)) / 2);
  border-radius: var(--rbtn);
  color: var(--muted);
  font-weight: 600;
  list-style: none;
  cursor: pointer;
  transition: background-color .15s ease;
}
.account-btn::-webkit-details-marker { display: none; }
.account-btn:hover { background: var(--hover); color: var(--text); }
.account-btn:active { background: var(--press); }
.account-menu[open] > .account-btn { background: var(--hover); color: var(--text); }
.avatar {
  display: grid;
  place-items: center;
  flex: none;
  width: var(--avatar);
  height: var(--avatar);
  border-radius: 50%;
  background: var(--press);
  color: var(--text);
  font-weight: 600;
  font-size: var(--fs-caption);
}
.account-name {
  min-width: 0;
  max-width: 16ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.account-caret {
  flex: none;
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform .15s ease;
}
.account-menu[open] .account-caret { transform: rotate(180deg); }
.menu {
  position: absolute;
  right: 0;
  top: calc(100% + var(--s1));
  z-index: 25;
  min-width: 256px;
  padding: var(--s1);
  background: var(--surface);
  border: var(--bw) solid var(--line-strong);
  border-radius: calc(var(--rinput) + var(--s1)); /* outer = inner + gap */
  --field-bg: var(--field-tile);
}
.menu-list { margin: 0; padding: 0; list-style: none; }
.menu-list form { margin: 0; }
.menu-list a, .menu-signout {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: var(--control-h);
  padding: 0 var(--s3);
  border: 0;
  border-radius: var(--rinput);
  background: none;
  color: var(--text);
  font-weight: 600;
  text-align: left;
  justify-content: flex-start;
  text-decoration: none;
}
.menu-list a:hover, .menu-signout:hover { background: var(--hover); }
.menu-list a:active, .menu-signout:active { background: var(--press); }
.menu-list a:focus-visible, .menu-signout:focus-visible { outline-offset: -2px; }
/* The current page: violet text only. The theme switch's inverse fill is the
   menu's one filled "selected". */
.menu-list a[aria-current="page"] { color: var(--accent-text); }
.menu-list li + li:last-child { margin-top: var(--s1); padding-top: var(--s1); border-top: var(--bw) solid var(--divider); }

/* The theme switch: System, Dark or Light, a segmented control (.seg). A
   plain form post without a script; account-menu.js applies it in place. */
.menu-theme { margin-top: var(--s1); padding-top: var(--s1); border-top: var(--bw) solid var(--divider); }
.theme-switch { margin: 0; padding: var(--s2) var(--s3) var(--s2); }
.menu-label { display: block; margin: 0 0 var(--s2); color: var(--muted); font-size: var(--fs-caption); line-height: var(--lh-caption); font-weight: 600; }
.theme-switch .seg { display: flex; }
.theme-switch .seg > * { flex: 1 1 0; min-width: 0; padding: 0 var(--s1); }

.page {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: var(--s5) var(--gutter) var(--s8);
}

/* --- Layout parts every page shares ---------------------------------------- */

/* The page's heading block: the h1 and an optional line under it, then
   --head-gap to the content. With an action (.page-head-row holds the h1 and
   the action) it is two columns (the human's choice, 2026-10-23, after Primer's
   PageHeader, Polaris, Atlassian and Grommet): the title and its description
   on the left, the description wrapping in that column and never running under
   the action; the action alone on the right, on the title's line. The row is
   display: contents, so the h1 and the action are the grid's own items. */
.page-head { margin-bottom: var(--head-gap); }
.page-head h1 { margin-bottom: var(--s1); }
.page-head > :last-child { margin-bottom: 0; }
.page-head:has(> .page-head-row) {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: var(--s3);
  align-items: start;
}
.page-head-row { display: contents; }
.page-head-row > :first-child { grid-column: 1; }
.page-head-row > :not(:first-child) { grid-column: 2; grid-row: 1; }
.page-head:has(> .page-head-row) > :not(.page-head-row) { grid-column: 1; }
.page-head-row h1 { margin: 0; }
/* The line under a heading row: the same gap as under a lone h1. */
.page-head-row + p { margin-top: var(--s1); }

/* Panels and notices stacked down a page, --stack apart. */
.stack { display: flex; flex-direction: column; gap: var(--stack); }
.stack > * { margin: 0; }

/* A panel: a borderless grey tile. Settings, People, Run cards, dialogs,
   confirm pages and the sign-in card all use it. Fields inside take the
   tile's field fill. */
.panel {
  padding: var(--pad-panel);
  background: var(--surface);
  border: 0;
  border-radius: var(--r);
  --field-bg: var(--field-tile);
}
.panel > :last-child { margin-bottom: 0; }
.panel-title {
  font-size: var(--fs-title);
  line-height: var(--lh-title);
  margin: 0 0 var(--s3);
}
/* The page's one centered card: sign-in, invite, reset, error, confirm pages. */
.panel-narrow { max-width: var(--dialog-max); margin: var(--s5) auto 0; }

/* A notice: a box led by a tone dot (the human's correction, 2026-10-23:
   notices keep their box). On the page it is a borderless tile; inside a tile
   it is an inset box in the page color. The dot sits in the left padding, out
   of the text's flow, so text that wraps lines up under the text, never under
   the dot. An error notice is a soft red box, on the page or in a tile. Fields
   use their own fill, so a notice never looks like a field. */
.notice {
  position: relative;
  margin: 0;
  padding: var(--pad-note);
  padding-left: calc(var(--s4) + var(--dot-lg) + var(--s2));
  background: var(--surface);
  border-radius: var(--r);
  overflow-wrap: anywhere;
}
.notice::before {
  content: "";
  position: absolute;
  left: var(--s4);
  top: calc(var(--s3) + (1lh - var(--dot-lg)) / 2); /* centered on the first line */
  width: var(--dot-lg);
  height: var(--dot-lg);
  border-radius: 50%;
  background: var(--ok);
}
.notice-warn::before { background: var(--warn); }
.notice-quiet::before { background: var(--line-strong); }
.notice-error { background: var(--danger-soft); }
.notice-error::before { background: var(--error); }
/* Inside a tile: an inset box in the page color, with the inner radius. */
.panel .notice { background: var(--bg); border-radius: var(--rinput); }
.panel .notice-error { background: var(--danger-soft); }

/* A list with lines between its items only, never above the first. */
.divided { list-style: none; margin: 0; padding: 0; }
.divided > * { padding-block: var(--row-py); }
.divided > :first-child { padding-top: 0; }
.divided > :last-child { padding-bottom: 0; }
.divided > * + * { border-top: var(--bw) solid var(--divider); }

/* A segmented control: a frame with a small inner padding, each segment its
   own rounded fill (the frame's radius less its padding and border, so the
   corners nest), no dividers. The Channels sort (links, aria-current) and the
   theme switch (buttons, aria-pressed) share it. */
.seg {
  display: inline-flex;
  gap: var(--s0);
  padding: 0;
  border: 0;
  border-radius: var(--rbtn);
  background: var(--field-bg); /* filled like a field; no inset, so 36 px like a button */
}
.seg > * {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--btn-h); /* drawn like a button; the tap area below makes it 44 */
  padding: 0 var(--s3);
  border: 0;
  border-radius: var(--rbtn); /* no inset, so the corners nest at one radius */
  background: none;
  color: var(--muted);
  font-weight: 400;
  text-decoration: none;
  white-space: nowrap;
}
.seg > :hover { background: var(--press); color: var(--text); }
.seg > :active { background: var(--press); }
.seg > [aria-current="true"], .seg > [aria-pressed="true"] { background: var(--inv); color: var(--on-inv); font-weight: 600; }
.seg > :focus-visible { outline-offset: 0; }

/* A small rounded count or label. */
.badge {
  display: inline-block;
  padding: 0 var(--s2);
  border: var(--bw) solid var(--press);
  border-radius: var(--rpill);
  background: var(--press);
  color: var(--text);
  font-family: var(--body);
  font-size: var(--fs-caption);
  font-weight: 600;
  letter-spacing: 0;
  line-height: 18px; /* 20 px tall with the border */
  white-space: nowrap;
  vertical-align: middle;
  font-variant-numeric: tabular-nums;
}
.badge-quiet { background: var(--hover); border-color: var(--hover); color: var(--muted); }

/* A status dot: filled when done, a ring while waiting or running. */
.dot {
  display: inline-block;
  flex: none;
  width: var(--dot);
  height: var(--dot);
  border-radius: 50%;
  background: var(--line-strong);
}
.dot-ok { background: var(--ok); }
.dot-warn { background: var(--warn); }
.dot-error { background: var(--error); }
.dot-running { background: none; box-shadow: inset 0 0 0 var(--bw-strong) var(--accent); }

/* A 44 px tall tap area on a small text link, without adding space around it:
   the ::after reaches past the text, the line box stays the text's height. */
.tap { position: relative; }
.tap::after {
  content: "";
  position: absolute;
  left: calc(-1 * var(--s1));
  right: calc(-1 * var(--s1));
  top: 50%;
  height: var(--tap);
  margin-top: calc(var(--tap) / -2);
}

/* A dialog over the page, and the same box as a page of its own without a script. */
.confirm-dialog {
  width: min(var(--dialog-max), calc(100% - 2 * var(--gutter)));
  margin: var(--s8) auto auto;
  color: var(--text);
  border: 0; /* the scrim sets it apart; the confirm page has no edge either */
}
.confirm-dialog::backdrop { background: var(--scrim); }
.confirm-dialog p, .confirm-panel p { margin: 0; }
.confirm-dialog .panel-title, .confirm-panel .panel-title { margin-bottom: var(--s2); overflow-wrap: anywhere; }
/* As a page of its own, the question is the page's heading. */
.confirm-panel .panel-title { font-size: var(--fs-heading); line-height: var(--lh-heading); }

/* An empty or no-match state: a calm line of muted text, no box. Its one
   action is a link. */
.empty { margin: 0; color: var(--muted); }
.empty p { margin: 0 0 var(--s1); }
.empty > :last-child { margin-bottom: 0; }
.empty[hidden] { display: none; }
.confirm-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--s2);
  margin: var(--s5) 0 0;
}

/* --- Controls -------------------------------------------------------------- */

button, input, select, textarea {
  font: inherit;
  color: inherit;
  -webkit-appearance: none;
  appearance: none;
  margin: 0;
}

button, .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  position: relative;
  min-height: var(--btn-h);
  padding: 0 var(--btn-px);
  border: var(--bw) solid var(--line-strong);
  border-radius: var(--rbtn);
  background: transparent;
  color: var(--text);
  font-family: var(--body);
  font-size: var(--fs-body);
  font-weight: 600;
  line-height: var(--lh-body);
  text-decoration: none;
  cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
/* Buttons draw at 36 px, and every one keeps a 44 px tap area: an invisible
   ::after reaching 4 px above and below. It reaches up and down only, so
   buttons side by side never share a target. The round check has its own. */
button:not(.check)::after, .btn::after, .seg > a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: var(--tap);
  margin-top: calc(var(--tap) / -2);
}
.btn-secondary { background: transparent; border-color: var(--line-strong); color: var(--text); }
/* A button in the heading row fits inside the h1's 32 px line, centered on
   it, so the line under the heading keeps its normal gap. */
.page-head-row .btn { margin-block: calc((var(--lh-display) - var(--btn-h)) / 2); }
button:hover, .btn:hover { background: var(--hover); }
button:active, .btn:active { background: var(--press); }

.btn-primary {
  background: var(--inv);
  border-color: var(--inv);
  color: var(--on-inv);
}
.btn-primary:hover { background: var(--inv-hover); border-color: var(--inv-hover); }
.btn-primary:active { background: var(--inv-press); border-color: var(--inv-press); }

.btn-danger {
  background: var(--danger);
  border-color: var(--danger);
  color: var(--on-danger);
}
.btn-danger:hover { background: var(--danger-hover); border-color: var(--danger-hover); }
.btn-danger:active { background: var(--danger-press); border-color: var(--danger-press); }

/* A quiet text button: violet text, a hover fill, no border. Its text lines up
   with the column edge it sits against (.btn-quiet-end at the right). */
.btn-quiet {
  padding: 0 var(--s2);
  border-color: transparent;
  background: none;
  color: var(--accent-text);
}
.btn-quiet:hover { background: var(--hover); }
.btn-quiet:active { background: var(--press); }
.btn-quiet-end { margin-right: calc(-1 * var(--s2)); }
/* A small icon before a button's text (Mark all read's check). */
.btn-icon {
  flex: none;
  width: var(--s4);
  height: var(--s4);
  margin-right: calc(-1 * var(--s1)); /* the button's gap is 8 px; the icon sits 4 px from its text */
  fill: none;
  stroke: currentColor;
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* The quiet button in red, for a step that removes something (it asks first). */
.btn-quiet-danger { color: var(--danger); }
.btn-quiet-danger:hover { background: var(--danger-soft); color: var(--danger-hover); }
.btn-quiet-danger:active { background: var(--danger-soft); color: var(--danger-press); }

button:disabled, .btn:disabled, .btn[aria-disabled="true"] {
  opacity: .45;
  cursor: not-allowed;
}
.btn-primary:disabled:hover { background: var(--inv); border-color: var(--inv); }
.btn-secondary:disabled:hover { background: transparent; }
.btn-danger:disabled:hover { background: var(--danger); border-color: var(--danger); }

.field { display: flex; flex-direction: column; gap: var(--s2); max-width: var(--form-max); }
.field label { font-weight: 600; line-height: var(--lh-label); }

/* Fields are filled, with no border: one step from where they sit (--field-bg),
   14 px corners like buttons, exactly --control-h tall. */
.input,
input[type="text"], input[type="url"], input[type="search"], input[type="password"], input:not([type]), select, textarea {
  width: 100%;
  height: var(--control-h);
  padding: 0 var(--s3);
  border: 0;
  border-radius: var(--rbtn);
  background-color: var(--field-bg);
  color: var(--text);
  font-family: var(--body);
  font-size: var(--fs-input);
  line-height: var(--control-h);
}
textarea { height: auto; min-height: calc(3 * var(--control-h)); padding: var(--s2) var(--s3); line-height: var(--lh-body); }
.input::placeholder, input::placeholder { color: var(--muted); opacity: 1; }
/* Focus: the violet ring. An error: a red ring drawn inside the fill while
   the field isn't focused, plus the error text. Never both rings at once. */
.input:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: var(--ring) solid var(--focus);
  outline-offset: 2px;
}
.input[aria-invalid="true"]:not(:focus-visible),
input[aria-invalid="true"]:not(:focus-visible),
select[aria-invalid="true"]:not(:focus-visible) {
  outline: var(--ring) solid var(--error);
  outline-offset: calc(-1 * var(--ring));
}
/* No browser clear glyph in the search field. */
input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.input:disabled, input:disabled { opacity: .5; }

.hint { font-size: var(--fs-caption); line-height: var(--lh-caption); color: var(--muted); margin: 0; }

/* Progress bar: a rounded violet fill in a quiet track (Run page card, Today's strip). */
.track {
  height: var(--s2);
  margin: var(--s3) 0 var(--s2);
  background: var(--press);
  border-radius: var(--rbtn);
  overflow: hidden;
}
.fill {
  height: 100%;
  background: var(--accent);
  border-radius: var(--rbtn);
  transition: width .4s ease;
}

/* Tiles and fields have no border; with forced colors (Windows high
   contrast) they get one back, so their edges still show. */
@media (forced-colors: active) {
  .panel, .card, .run-strip, .notice-error, .seg, .input, input, select, textarea { border: var(--bw) solid; }
}

@media (prefers-reduced-motion: reduce) {
  button, .btn, .account-btn, .account-caret { transition: none; }
  .fill { transition: none; }
}

/* --- Phone: one-row header, the menu as a bottom tab bar -------------------- */

@media (max-width: 600px) {
  :root { --pad-panel: var(--s4); }

  /* Phones: the title and the action keep their row; the description runs
     the full width under both. */
  .page-head:has(> .page-head-row) > :not(.page-head-row) { grid-column: 1 / -1; }

  .site-header .bar { flex-wrap: nowrap; }
  .brand { font-size: var(--fs-title); line-height: var(--lh-title); }
  .account-name { max-width: 12ch; }
  .panel-narrow { margin-top: var(--s2); }

  .tabs {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 20;
    min-height: var(--tabbar-h);
    padding-bottom: env(safe-area-inset-bottom, 0px);
    background: var(--surface);
    border-top: var(--bw) solid var(--divider); /* apart from the cards scrolling under it */
  }
  .tabs .nav { gap: 0; }
  .tabs .nav li { flex: 1 1 0; min-width: 0; }
  .tabs .nav a {
    width: 100%;
    min-height: var(--tabbar-h);
    padding: 0 var(--s1);
    border-radius: 0;
    background: none;
  }
  .tabs .nav a:hover { background: var(--hover); }
  .tabs .nav a:focus-visible { outline-offset: -4px; }
  .tabs .nav a[aria-current="page"] { position: relative; background: none; }
  /* The selected tab: a short violet bar, centered at the top, and violet text. */
  .tabs .nav a[aria-current="page"]::before {
    content: "";
    position: absolute;
    top: 0;
    left: 50%;
    width: var(--s5);
    height: var(--bar);
    margin-left: calc(var(--s5) / -2);
    border-radius: 0 0 var(--bar) var(--bar);
    background: var(--accent);
  }
  /* Focus and in-page jumps never stop behind the tab bar. */
  html:has(.has-tabs) { scroll-padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px) + var(--s2)); }
  .has-tabs .page {
    padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px) + var(--s6));
  }
}
