/* Design tokens + styles for server-rendered markup (auth pages, app header).
   The editor surface itself is styled by the bundled frontend CSS.

   Scales below (space, radius, control, text, shadow) are complete ladders and
   stay complete even where a rung is currently unused. One-off tokens are not:
   if nothing references one, it is deleted rather than left as an intention.

   This file loads first on every page — including the dev harness, which borrows
   it through Vite's publicDir — so the bundled CSS never needs `var(--x, literal)`
   fallbacks. It must not grow any: a fallback is a second palette, and second
   palettes drift. See DESIGN.md. */

:root {
  /* ---- neutrals ----------------------------------------------------------
     Warm, not cool — and warmer again since pass 3. A blue-gray next to white
     reads as a screenshot of a document; a warm one reads as paper, and the
     paper is now a real surface rather than pure white. */
  --pasty-gray-0: #ffffff;
  --pasty-gray-25: #fffefa; /* the paper */
  --pasty-gray-50: #f4f2ec; /* the chrome band, and code wells */
  --pasty-gray-100: #eae7df; /* the field */
  --pasty-gray-150: #e4e0d8;
  --pasty-gray-200: #d9d5cd;
  --pasty-gray-300: #bcb5a9;
  --pasty-gray-400: #8f8a82; /* disabled text, 3.3:1 */
  --pasty-gray-600: #6b675f; /* muted text, 5.5:1 */
  --pasty-gray-700: #57524b; /* secondary document text, 7.7:1 */
  --pasty-gray-800: #35322d; /* icons */
  --pasty-gray-900: #27241f; /* body text */

  /* ---- ink (the dark ramp) -----------------------------------------------
     Authored against the light ramp, not derived from it: an inverted ramp is
     what makes a dark mode look inverted. Warm charcoal, never black, and the
     text end stops short of white. Never consumed directly — only the semantic
     layer below reads it. */
  /* Four depths, and only four: the field, the chrome band, the paper, and
     raised. Anything that wants to recede inside the page — a code well, an
     inline code chip — uses the band's depth, so a well and the chrome are
     the same plane seen from different sides. Giving each its own
     near-identical value was five blacks pretending to be a system. */
  --pasty-ink-50: #151412; /* the field */
  --pasty-ink-100: #1e1d1b; /* the chrome band, and code wells */
  --pasty-ink-150: #282623; /* the paper */
  --pasty-ink-200: #2f2d2a; /* raised: menus, popovers, the banner */
  --pasty-ink-300: #383633;
  --pasty-ink-400: #45423d;
  --pasty-ink-500: #5c5852;
  --pasty-ink-600: #a3a09a; /* muted text, 5.9:1 on the paper */
  --pasty-ink-700: #c5bfb5; /* secondary document text, 8.2:1 */
  --pasty-ink-800: #cdc9c2; /* icons */
  --pasty-ink-900: #ece7de; /* body text, 12.2:1 on the paper */

  /* ---- accent ------------------------------------------------------------
     One blue, and it means one thing: the caret, focus, selection, a link's
     underline, the palette's check. Calmer since pass 3 — deeper and less
     saturated, so it never reads as a button. It lightens in dark mode rather
     than darkening, and so hover and pressed lighten too, which is the reverse
     of light mode. Light 6.5:1 on the paper, dark 7.1:1, and both carry text
     on the fill. Dark runs a little brighter on purpose: a link that is dimmer
     than the prose around it reads as an afterthought, and the caret is one or
     two pixels wide. */
  --pasty-accent: light-dark(#2f5ba8, #93b3e8);
  --pasty-accent-hover: light-dark(#264b8e, #a6c0ec);
  --pasty-accent-down: light-dark(#1e3b70, #b8ccf0);
  --pasty-accent-soft: light-dark(#eef2f9, #23304a);
  --pasty-accent-active: light-dark(#dde6f5, #2c3d5e);
  --pasty-selection: light-dark(#d4e0f4, #30456a);

  /* ---- danger ------------------------------------------------------------ */
  --pasty-danger: light-dark(#b42318, #f2837a);
  --pasty-danger-soft: light-dark(#fdf3f2, #2a1a18);
  --pasty-danger-border: light-dark(#f0cac5, #5a2f2a);

  /* ---- the filled button -------------------------------------------------
     Ink, not accent: a primary button is the strongest neutral on the page,
     which leaves the accent free to mean the caret and the links. Inverts
     with the theme — light text on ink, ink text on light. */
  --pasty-button-fill: light-dark(var(--pasty-gray-900), var(--pasty-ink-900));
  --pasty-button-fill-hover: light-dark(var(--pasty-gray-800), var(--pasty-gray-0));
  --pasty-button-text: light-dark(var(--pasty-gray-0), var(--pasty-ink-50));

  /* ---- keycaps -----------------------------------------------------------
     A fill, a hairline, and a one-pixel lip that pressing removes. Drawn once
     (`.kbd__key`) for the header cue, the palette's rows and the menu's hint. */
  --pasty-key-fill: light-dark(#f9f8f5, #393632);
  --pasty-key-border: light-dark(#d8d5cf, #4c4943);
  --pasty-key-lip: light-dark(#c6c2ba, #171614);
  --pasty-key-text: light-dark(#454340, #d3cec6);

  /* ---- interaction washes ------------------------------------------------
     Neutral, never a tint of the accent: hover is not an action. Ink on light,
     light on ink. */
  /* Dark runs hotter than a straight inversion: the same percentage of white on
     charcoal is a far smaller perceptual step than that percentage of ink on
     white, and a hover you have to look for is not a hover. */
  --pasty-hover: light-dark(rgb(32 31 29 / 5%), rgb(255 255 255 / 10%));
  --pasty-hover-strong: light-dark(rgb(32 31 29 / 9%), rgb(255 255 255 / 16%));
  /* A translucent hairline for the palette's highlight: the edge that makes a
     wash read as a row rather than a smudge. */
  --pasty-edge: light-dark(rgb(32 31 29 / 6%), rgb(255 255 255 / 6%));

  /* ---- semantic layer ----------------------------------------------------
     THE RULE: components consume these, never the ramps above. A rule that
     reaches past this layer into `--pasty-gray-*` is a rule a theme cannot
     re-point, which is how a stylesheet ends up forked. */

  /* surfaces, from furthest back to furthest forward. Three planes carry the
     composition: the field behind everything, the band the chrome sits on,
     and the paper — the brightest, warmest thing on screen. The band sits
     between the other two, so the chrome is neither paper nor field. */
  --pasty-workspace: light-dark(var(--pasty-gray-100), var(--pasty-ink-50));
  --pasty-chrome: light-dark(var(--pasty-gray-50), var(--pasty-ink-100));
  --pasty-chrome-rule: light-dark(var(--pasty-gray-150), #2c2a27);
  --pasty-surface: light-dark(var(--pasty-gray-25), var(--pasty-ink-150));
  /* A breath of the paper's warmth in light, so a menu over the page does not
     read as a cooler white floating above it. */
  --pasty-surface-raised: light-dark(#fffefb, var(--pasty-ink-200));
  /* Deliberately the same value as the chrome band: two names, one depth. A
     code well is not a different kind of surface from the band, it is the
     same plane seen inside the page. */
  --pasty-surface-sunken: light-dark(var(--pasty-gray-50), var(--pasty-ink-100));
  /* Behind the command palette. Dark goes further than a proportional
     inversion: a light scrim over a dark page barely reads, and the point of a
     scrim is that the page behind it stops competing. Safe to consume from
     `::backdrop`, which inherits from its originating element in every browser
     that has `light-dark()` at all. */
  --pasty-scrim: light-dark(rgb(32 31 29 / 24%), rgb(0 0 0 / 56%));

  /* text, in four tiers that mean four different things:
       --pasty-text            primary document content
       --pasty-text-secondary  secondary *document* content — quotes, markers,
                               the deepest heading, a completed task
       --pasty-text-muted      muted *application* text — save status, help
       --pasty-text-disabled   a control you cannot use
     The document never reaches past the second tier. It used to: h6, list
     markers and checked tasks were all on the chrome's muted value, which put
     document content at the same contrast as the save-status line. */
  --pasty-text: light-dark(var(--pasty-gray-900), var(--pasty-ink-900));
  --pasty-text-secondary: light-dark(var(--pasty-gray-700), var(--pasty-ink-700));
  --pasty-text-muted: light-dark(var(--pasty-gray-600), var(--pasty-ink-600));
  --pasty-text-disabled: light-dark(var(--pasty-gray-400), #76726b);
  --pasty-icon: light-dark(var(--pasty-gray-800), var(--pasty-ink-800));

  /* lines */
  --pasty-border: light-dark(var(--pasty-gray-200), var(--pasty-ink-400));
  --pasty-border-soft: light-dark(var(--pasty-gray-150), var(--pasty-ink-300));
  --pasty-border-strong: light-dark(var(--pasty-gray-300), var(--pasty-ink-500));
  --pasty-border-strong-hover: light-dark(var(--pasty-gray-400), #6f6b64);
  /* The section rule is short now, so it can afford to be the stronger line. */
  --pasty-rule: light-dark(var(--pasty-gray-300), var(--pasty-ink-500));

  /* quiet fills */
  --pasty-fill-quiet: light-dark(var(--pasty-gray-100), var(--pasty-ink-200));
  --pasty-fill-quiet-strong: light-dark(var(--pasty-gray-200), var(--pasty-ink-300));

  /* accent-adjacent */
  --pasty-on-accent: light-dark(var(--pasty-gray-0), #10203f);
  /* A pale tint in light; a translucent accent in dark, so the halo reads on
     the document, on a menu panel and in a sunken code well alike. */
  /* Derived, not copied: this had already drifted a shade behind the accent
     once, which is what a hand-written tint of another token always does. */
  --pasty-focus-ring: light-dark(#eef2f9, color-mix(in srgb, var(--pasty-accent) 35%, transparent));

  /* document constructs. Inline code and code wells go *darker* than the page
     in both themes, which is what stops them reading as bright pills. A table
     is rules, not a grid, and its header rule is the strong one. */
  --pasty-quote-border: light-dark(#cfc9bd, var(--pasty-ink-400));
  --pasty-code-border: light-dark(var(--pasty-gray-150), var(--pasty-ink-300));
  --pasty-table-border: light-dark(var(--pasty-gray-150), var(--pasty-ink-300));
  --pasty-table-header-border: light-dark(var(--pasty-gray-300), var(--pasty-ink-500));

  /* ---- radius ------------------------------------------------------------
     Tighter corners read as machinery. */
  --pasty-radius-sm: 5px; /* embedded: toolbar buttons, menu rows */
  --pasty-radius-md: 6px; /* freestanding: buttons, inputs */
  --pasty-radius-lg: 10px; /* floating: menus, cards, the page */
  --pasty-radius: var(--pasty-radius-md);

  /* ---- space (4px grid) -------------------------------------------------- */
  --pasty-space-1: 4px;
  --pasty-space-2: 8px;
  --pasty-space-3: 12px;
  --pasty-space-4: 16px;
  --pasty-space-5: 20px;
  --pasty-space-6: 24px;
  --pasty-space-7: 32px;
  --pasty-space-8: 40px;

  /* ---- control heights --------------------------------------------------- */
  --pasty-control-sm: 28px; /* toolbar */
  --pasty-control-md: 32px; /* header chrome, menu rows */
  --pasty-control-lg: 40px; /* auth forms */

  /* ---- UI type ----------------------------------------------------------- */
  --pasty-text-xs: 12px;
  --pasty-text-sm: 13px;
  --pasty-text-md: 14px;
  --pasty-text-lg: 16px;
  --pasty-text-xl: 20px;

  /* ---- elevation --------------------------------------------------------- */
  --pasty-shadow-sm: 0 1px 2px light-dark(rgb(32 31 29 / 6%), transparent);
  --pasty-shadow-md: 0 2px 4px light-dark(rgb(32 31 29 / 6%), rgb(0 0 0 / 28%)),
    0 8px 24px light-dark(rgb(32 31 29 / 10%), rgb(0 0 0 / 40%));
  --pasty-shadow-lg: 0 4px 8px light-dark(rgb(32 31 29 / 8%), rgb(0 0 0 / 34%)),
    0 16px 40px light-dark(rgb(32 31 29 / 14%), rgb(0 0 0 / 48%));

  /* ---- motion ------------------------------------------------------------
     Two durations. Everything animated references one of them, so
     prefers-reduced-motion can switch the whole product off at the token. */
  --pasty-ease: cubic-bezier(0.2, 0, 0, 1);
  --pasty-t-fast: 80ms; /* state: hover, press, active */
  --pasty-t-base: 140ms; /* entrance: menus, chips, banner */

  /* ---- typefaces --------------------------------------------------------- */
  --pasty-ui-font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial,
    sans-serif;
  /* The document stack: the same family as the UI by design — it differentiates
     itself by size, leading and measure — plus an emoji tail, because agent
     output is full of them. */
  --pasty-font: system-ui, -apple-system, "Segoe UI Variable Text", "Segoe UI", Roboto,
    "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji",
    "Segoe UI Emoji", "Noto Color Emoji";
  --pasty-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Cascadia Code",
    "Roboto Mono", "Liberation Mono", monospace;

  /* ---- layout ------------------------------------------------------------ */
  /* 44 is a floor, not a preference: a 32px control plus a 2px focus ring at a
     2px offset occupies 40px, and 40 would clip every ring against the rule. */
  --pasty-header-height: 44px;
  --pasty-toolbar-height: 41px; /* 6 + 28px control + 6 + the 1px rule */
  /* One number for the header, the toolbar and the workspace, so the chrome and
     the sheet cannot drift apart. See `.app-header__inner`. */
  --pasty-rail-gutter: var(--pasty-space-5);
  /* The workspace subtracts the whole chrome band, so the page fills the window
     exactly once and never invents a scrollbar. */
  --pasty-chrome-offset: calc(var(--pasty-header-height) + var(--pasty-toolbar-height));
  --pasty-page-max-width: 940px;
  --pasty-prose-measure: 640px; /* ~75 characters at 17px */

  /* System, and it costs no JavaScript: `light-dark()` above reads this, and
     this reads the OS. The attribute rules below are the manual override, and
     they are the only thing theme.ts writes. */
  color-scheme: light dark;
}

:root[data-theme="light"] {
  color-scheme: light;
}

:root[data-theme="dark"] {
  color-scheme: dark;
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --pasty-t-fast: 0ms;
    --pasty-t-base: 0ms;
  }
}




/* `light-dark()` is the whole theme mechanism, and this file forbids
   `var(--x, literal)` fallbacks — so on a browser without it every themed
   token would resolve to nothing and Pasty would render as transparent
   panels and inherited text. This block makes the failure mode "light mode"
   instead, which is exactly what Pasty was before dark mode existed.
   Generated from the pairs above; frontend/tests/theme-boot.test.ts fails if
   the two ever disagree. */
@supports not (color: light-dark(#fff, #000)) {
  :root {
    color-scheme: light;
    --pasty-accent: #2f5ba8;
    --pasty-accent-hover: #264b8e;
    --pasty-accent-down: #1e3b70;
    --pasty-accent-soft: #eef2f9;
    --pasty-accent-active: #dde6f5;
    --pasty-selection: #d4e0f4;
    --pasty-danger: #b42318;
    --pasty-danger-soft: #fdf3f2;
    --pasty-danger-border: #f0cac5;
    --pasty-button-fill: var(--pasty-gray-900);
    --pasty-button-fill-hover: var(--pasty-gray-800);
    --pasty-button-text: var(--pasty-gray-0);
    --pasty-key-fill: #f9f8f5;
    --pasty-key-border: #d8d5cf;
    --pasty-key-lip: #c6c2ba;
    --pasty-key-text: #454340;
    --pasty-hover: rgb(32 31 29 / 5%);
    --pasty-hover-strong: rgb(32 31 29 / 9%);
    --pasty-edge: rgb(32 31 29 / 6%);
    --pasty-workspace: var(--pasty-gray-100);
    --pasty-chrome: var(--pasty-gray-50);
    --pasty-chrome-rule: var(--pasty-gray-150);
    --pasty-surface: var(--pasty-gray-25);
    --pasty-surface-raised: #fffefb;
    --pasty-surface-sunken: var(--pasty-gray-50);
    --pasty-scrim: rgb(32 31 29 / 24%);
    --pasty-text: var(--pasty-gray-900);
    --pasty-text-secondary: var(--pasty-gray-700);
    --pasty-text-muted: var(--pasty-gray-600);
    --pasty-text-disabled: var(--pasty-gray-400);
    --pasty-icon: var(--pasty-gray-800);
    --pasty-border: var(--pasty-gray-200);
    --pasty-border-soft: var(--pasty-gray-150);
    --pasty-border-strong: var(--pasty-gray-300);
    --pasty-border-strong-hover: var(--pasty-gray-400);
    --pasty-rule: var(--pasty-gray-300);
    --pasty-fill-quiet: var(--pasty-gray-100);
    --pasty-fill-quiet-strong: var(--pasty-gray-200);
    --pasty-on-accent: var(--pasty-gray-0);
    --pasty-focus-ring: #eef2f9;
    --pasty-quote-border: #cfc9bd;
    --pasty-code-border: var(--pasty-gray-150);
    --pasty-table-border: var(--pasty-gray-150);
    --pasty-table-header-border: var(--pasty-gray-300);
    --pasty-shadow-sm: 0 1px 2px rgb(32 31 29 / 6%);
    --pasty-shadow-md: 0 2px 4px rgb(32 31 29 / 6%), 0 8px 24px rgb(32 31 29 / 10%);
    --pasty-shadow-lg: 0 4px 8px rgb(32 31 29 / 8%), 0 16px 40px rgb(32 31 29 / 14%);
  }
}

* {
  box-sizing: border-box;
}

/* A class that sets `display` outranks the user agent's `[hidden]` rule, so
   toggling the attribute would silently stop hiding things. */
[hidden] {
  display: none !important;
}

html,
body {
  margin: 0;
  padding: 0;
}

body {
  background: var(--pasty-workspace);
  color: var(--pasty-text);
  font-family: var(--pasty-ui-font);
  font-size: var(--pasty-text-md);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

a {
  color: var(--pasty-accent);
}

:focus-visible {
  outline: 2px solid var(--pasty-accent);
  outline-offset: 2px;
}

/* Entrance for anything that appears in place: menus, the copied chip, the
   banner. Closing is instant — waiting for something to leave is the one kind
   of animation that always reads as slowness. */
@keyframes pasty-pop {
  from {
    opacity: 0;
    transform: translateY(2px);
  }
}

/* ---------- buttons (shared by header + auth) ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--pasty-space-2);
  height: var(--pasty-control-md);
  padding: 0 var(--pasty-space-3);
  border: 1px solid transparent;
  border-radius: var(--pasty-radius-md);
  font: inherit;
  font-size: var(--pasty-text-sm);
  font-weight: 500;
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  background: transparent;
  color: var(--pasty-text);
  transition:
    background-color var(--pasty-t-fast) var(--pasty-ease),
    border-color var(--pasty-t-fast) var(--pasty-ease),
    color var(--pasty-t-fast) var(--pasty-ease);
}

/* Ink, not accent — see the token. */
.btn--primary {
  background: var(--pasty-button-fill);
  color: var(--pasty-button-text);
}

.btn--primary:hover {
  background: var(--pasty-button-fill-hover);
}

.btn--primary:active {
  background: var(--pasty-button-fill);
}

/* An outline flush against a filled control is invisible. A surface-coloured
   gap between the two rings is what makes focus readable on it. */
.btn--primary:focus-visible {
  outline: none;
  box-shadow:
    0 0 0 2px var(--pasty-surface),
    0 0 0 4px var(--pasty-accent);
}

.btn--outline {
  border-color: var(--pasty-border);
  color: var(--pasty-text);
}

.btn--outline:hover,
.btn--quiet:hover {
  background: var(--pasty-hover);
}

.btn--outline:active,
.btn--quiet:active {
  background: var(--pasty-hover-strong);
}

.btn--quiet {
  color: var(--pasty-icon);
}

.btn--quiet:hover {
  color: var(--pasty-text);
}

.btn--block {
  width: 100%;
  height: var(--pasty-control-lg);
  font-size: var(--pasty-text-md);
}

.btn:disabled,
.btn[aria-disabled="true"] {
  color: var(--pasty-text-disabled);
  background: var(--pasty-fill-quiet);
  border-color: transparent;
  cursor: default;
}

.btn--primary:disabled {
  background: var(--pasty-fill-quiet-strong);
  color: var(--pasty-text-disabled);
}

/* ---------- menus (shared primitives) ---------- */

.menu {
  position: relative;
}

.menu > summary {
  list-style: none;
  user-select: none;
}

.menu > summary::-webkit-details-marker {
  display: none;
}

.menu[open] > summary.btn {
  background: var(--pasty-hover-strong);
  color: var(--pasty-text);
}

.menu__panel {
  position: absolute;
  top: calc(100% + var(--pasty-space-2));
  right: 0;
  z-index: 40;
  width: 240px;
  max-height: 60vh;
  overflow-y: auto;
  padding: var(--pasty-space-1);
  background: var(--pasty-surface-raised);
  border: 1px solid var(--pasty-border);
  border-radius: var(--pasty-radius-lg);
  box-shadow: var(--pasty-shadow-md);
  animation: pasty-pop var(--pasty-t-base) var(--pasty-ease);
}

.menu__item {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  min-height: 30px;
  padding: 3px var(--pasty-space-2);
  border: 0;
  border-radius: var(--pasty-radius-sm);
  background: transparent;
  color: var(--pasty-text);
  font: inherit;
  font-size: var(--pasty-text-sm);
  text-align: left;
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
  transition: background-color var(--pasty-t-fast) var(--pasty-ease);
}

.menu__item:hover {
  background: var(--pasty-hover);
}

.menu__item:active {
  background: var(--pasty-hover-strong);
}

/* A row with its shortcut on the right. `.menu__item` is one ellipsised line
   with no second slot, so the label gets its own box and does the truncating. */
.menu__item--shortcut {
  justify-content: space-between;
}

.menu__item-label {
  overflow: hidden;
  text-overflow: ellipsis;
}

.menu__hint {
  flex: 0 0 auto;
  color: var(--pasty-text-muted);
  font-size: 11px;
}

/* A section label: small caps, quietly tracked. The palette's sections use
   the same register, so the two surfaces share one word for "a group". */
.menu__header {
  margin: 0;
  padding: var(--pasty-space-2) var(--pasty-space-2) var(--pasty-space-1);
  color: var(--pasty-text-muted);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The account menu's first header is the email address, not a section. */
.menu__header[title] {
  font-size: 11.5px;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
}

/* A radio row: the checkmark is the state, so the row keeps its normal weight
   and the column stays aligned whether or not a row is selected. */
.menu__item--choice::before {
  content: "";
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  background-color: currentcolor;
  opacity: 0;
  mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m5 12.5 4.5 4.5L19 7.5" fill="none" stroke="black" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>');
  mask-repeat: no-repeat;
  mask-position: center;
}

.menu__item--choice[aria-checked="true"]::before {
  opacity: 1;
}

/* The check is the state; the row keeps its ink. */
.menu__item--choice[aria-checked="true"] {
  color: var(--pasty-text);
}

.menu__separator {
  height: 0;
  margin: var(--pasty-space-1) 0;
  border: 0;
  border-top: 1px solid var(--pasty-border-soft);
}

/* ---------- share popover ---------- */

/* Two toggles and a link: Private / Shared, then Read-only / Editable, then the
   link button that opens the receipt. The popover is still a details.menu, so
   menus.ts keeps giving it Escape, click-outside close and one-open-at-a-time —
   but the controller cancels the summary's own toggle, so the link button can
   only ever open it. The panel holds no .menu__item rows, which is what keeps
   the menus' arrow-key handler out of the way of the URL. */

.share-controls {
  display: inline-flex;
  align-items: center;
  gap: var(--pasty-space-1);
}

/* Nothing moves under the pointer. The slots that only mean something once a
   document is shared are held, not removed: this group is right-aligned, so a
   slot appearing beside Shared would push it out from under a pointer about to
   click it again. */
.share-controls__toggle[data-reserved],
.share-menu[data-reserved] {
  visibility: hidden;
}

/* Every word a toggle can show in one grid cell: the button is as wide as the
   longest of them, so the word changes without the button resizing. */
.share-toggle__labels {
  display: grid;
  place-items: center;
}

.share-toggle__label {
  grid-area: 1 / 1;
  display: inline-flex;
  align-items: center;
  gap: var(--pasty-space-1);
  opacity: 0;
  transition: opacity var(--pasty-t-base) var(--pasty-ease);
}

.share-toggle__label[data-current] {
  opacity: 1;
}

/* Shared and Editable are resting states, not flashes: the header says so
   until they stop being true. One step out of the quiet register, which is as
   loud as a status ever gets up there. */
.share-toggle[data-state="shared"],
.share-edit-toggle[data-state="editable"] {
  color: var(--pasty-text);
}

/* The server is catching up with the click. Still clickable — a second click
   takes the first back — so this is a hint, not a disabled state. */
.share-controls__toggle[aria-busy="true"] {
  opacity: 0.6;
}

/* The link button: a square the size of the header's other controls, its link
   and its Copied check sharing one cell. */
.share-menu__trigger--icon {
  width: var(--pasty-control-md);
  padding: 0;
}

/* A column, so its buttons stretch to the panel: a <button> with `width: auto`
   shrinks to its label however block-level you make it. */
.share-menu__panel {
  display: flex;
  flex-direction: column;
  width: 320px;
  padding: var(--pasty-space-2);
}

.share-menu__heading {
  display: flex;
  align-items: center;
  gap: var(--pasty-space-2);
  margin: 0;
  padding: var(--pasty-space-1) var(--pasty-space-2);
  font-size: var(--pasty-text-sm);
  font-weight: 500;
}

.share-menu__check {
  display: inline-flex;
}

.share-menu__body,
.share-menu__note {
  margin: 0;
  padding: var(--pasty-space-1) var(--pasty-space-2);
  color: var(--pasty-text-muted);
  font-size: var(--pasty-text-xs);
}

/* The note keeps its line whether or not it is saying anything: everything the
   pointer might be reaching for — the URL, Copy, Stop sharing — sits under it,
   and none of them may move because a message arrived or left. */
.share-menu__note {
  min-height: 1lh;
}

.share-menu__link {
  display: flex;
  align-items: center;
  gap: var(--pasty-space-2);
  padding: var(--pasty-space-1) var(--pasty-space-2);
}

/* The CLI token page's treatment for a revealed secret, sized for a panel:
   monospace, one line, ellipsised — and one click still selects the whole
   thing, tail included. */
.share-menu__url,
.share-menu__view-url {
  flex: 1 1 auto;
  min-width: 0;
  padding: var(--pasty-space-2) var(--pasty-space-3);
  background: var(--pasty-surface);
  border: 1px solid var(--pasty-border-soft);
  border-radius: var(--pasty-radius-sm);
  font-family: var(--pasty-mono);
  font-size: var(--pasty-text-xs);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  user-select: all;
}

.share-menu__copy,
.share-menu__view-copy {
  flex: 0 0 auto;
}

/* Inset to the text's left edge: it is the card's conclusion, not a banner. */
.share-menu__share {
  margin: var(--pasty-space-2) var(--pasty-space-2) var(--pasty-space-1);
}

/* The view link on the editable face: a footnote to the edit link above it,
   with a label so the two are never confused for each other. */
.share-menu__view-label {
  padding-bottom: 0;
}

.share-menu__view-url {
  color: var(--pasty-text-muted);
}

.share-menu__auth {
  display: flex;
  gap: var(--pasty-space-2);
  padding: 0 var(--pasty-space-2) var(--pasty-space-2);
}

/* ---------- command palette ---------- */

/* A native <dialog> in the top layer: the backdrop, the focus trap and Escape
   come from the platform, the way the menus are native <details>. Held near the
   top rather than centred, because a list that grows downwards should not move
   the field it grew from. */
.palette {
  width: min(560px, calc(100vw - 2 * var(--pasty-space-5)));
  max-height: min(72vh, 660px);
  margin: 12vh auto 0;
  padding: 0;
  overflow: hidden;
  background: var(--pasty-surface-raised);
  color: var(--pasty-text);
  border: 1px solid var(--pasty-border);
  border-radius: var(--pasty-radius-lg);
  box-shadow: var(--pasty-shadow-lg);
}

/* `display` belongs on the open state and nowhere else: an unqualified
   `display: flex` here would outrank the user agent's `dialog:not([open])` rule
   and leave the palette on screen permanently. */
.palette[open] {
  display: flex;
  flex-direction: column;
  animation: pasty-pop var(--pasty-t-base) var(--pasty-ease);
}

.palette::backdrop {
  background: var(--pasty-scrim);
}

.palette__field {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;
  padding: 0 14px;
  border-bottom: 1px solid var(--pasty-border-soft);
}

.palette__glyph {
  flex: 0 0 auto;
  color: var(--pasty-text-muted);
}

.palette__input {
  flex: 1 1 auto;
  min-width: 0;
  height: 46px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--pasty-text);
  font: inherit;
  font-size: 15px;
}

.palette__input::placeholder {
  color: var(--pasty-text-muted);
}

/* The panel is the focus indicator. A ring around the only focusable thing
   inside it would be a box drawn inside a box. */
.palette__input:focus-visible {
  outline: none;
}

.palette__list {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 6px;
}

/* The menu's small caps: one register for "a group" on both surfaces. */
.palette__section {
  margin: 0;
  padding: 10px 10px var(--pasty-space-1);
  color: var(--pasty-text-muted);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.palette__group + .palette__group .palette__section {
  padding-top: 14px;
}

.palette__option {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 30px;
  padding: 3px 10px;
  border-radius: var(--pasty-radius-sm);
  font-size: 13.5px;
  cursor: pointer;
}

/* One highlight, and the pointer sets the same one the arrow keys do — two
   highlights would be two answers to "what does Enter run?". Neutral, not a
   tint of the accent: this marks a position, not an action. The hairline is
   what makes it read as an edge rather than a smudge. */
.palette__option.is-active {
  background: var(--pasty-hover-strong);
  box-shadow: inset 0 0 0 1px var(--pasty-edge);
}

.palette__label {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* Two lines in a row that is otherwise one. Only rows whose label cannot carry
   the whole meaning get a description — "Enable Vim mode" says what it does,
   "Use Vim keybindings while editing" says what that means. */
.palette__text {
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  flex-direction: column;
  gap: 1px;
}

.palette__description {
  overflow: hidden;
  color: var(--pasty-text-muted);
  font-size: 11.5px;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* The row's chord: a container of caps, one per key, drawn by `.kbd__key`
   under "keycaps". The label stays the thing you read; the caps are the thing
   you learn. */
.palette__key {
  flex: 0 0 auto;
}

.palette__check {
  flex: 0 0 auto;
  color: var(--pasty-accent);
}

.palette__empty {
  margin: 0;
  padding: var(--pasty-space-4);
  color: var(--pasty-text-muted);
  font-size: var(--pasty-text-sm);
}

/* The palette's own keys, taught in a footer: the one place the chrome
   explains itself, because the list above it is the thing being explained. */
.palette__footer {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: var(--pasty-space-4);
  padding: 7px 14px;
  border-top: 1px solid var(--pasty-border-soft);
  color: var(--pasty-text-muted);
  font-size: 11.5px;
}

.palette__hint {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

/* ---------- settings ---------- */

/* Built on the palette's dialog: same top layer, same backdrop, same escape.
   Centred rather than held near the top — nothing here grows, so there is no
   field for a growing list to push around. */
.settings {
  width: min(480px, calc(100vw - 2 * var(--pasty-space-5)));
  max-height: min(80vh, 640px);
  margin: auto;
  padding: 0;
  overflow: hidden;
  background: var(--pasty-surface-raised);
  color: var(--pasty-text);
  border: 1px solid var(--pasty-border-soft);
  border-radius: var(--pasty-radius-lg);
  box-shadow: var(--pasty-shadow-lg);
}

/* See the note on .palette[open]: an unqualified `display` here would outrank
   the user agent's `dialog:not([open])` rule. */
.settings[open] {
  display: flex;
  flex-direction: column;
  animation: pasty-pop var(--pasty-t-base) var(--pasty-ease);
}

.settings::backdrop {
  background: var(--pasty-scrim);
}

.settings__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--pasty-space-3);
  flex: 0 0 auto;
  padding: var(--pasty-space-3) var(--pasty-space-4);
  border-bottom: 1px solid var(--pasty-border-soft);
}

.settings__title {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
}

.settings__body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: var(--pasty-space-2) var(--pasty-space-4) var(--pasty-space-4);
}

.settings__group + .settings__group {
  margin-top: var(--pasty-space-4);
  padding-top: var(--pasty-space-3);
  border-top: 1px solid var(--pasty-border-soft);
}

.settings__section {
  margin: var(--pasty-space-3) 0 var(--pasty-space-2);
  color: var(--pasty-text-muted);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.settings__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--pasty-space-4);
}

.settings__text {
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  flex-direction: column;
  gap: 2px;
}

.settings__description {
  color: var(--pasty-text-muted);
  font-size: 12.5px;
}

/* A real switch: role="switch" plus a control that looks like one. The knob is
   the only thing that moves, so the row's height never changes. */
.settings__switch {
  flex: 0 0 auto;
  width: 40px;
  height: 24px;
  padding: 0;
  border: 1px solid var(--pasty-border);
  border-radius: 999px;
  background: var(--pasty-surface-sunken);
  cursor: pointer;
  transition: background var(--pasty-t-fast) var(--pasty-ease);
}

.settings__switch[aria-checked="true"] {
  border-color: var(--pasty-accent);
  background: var(--pasty-accent);
}

.settings__knob {
  display: block;
  width: 16px;
  height: 16px;
  margin-inline-start: 3px;
  border-radius: 50%;
  background: var(--pasty-surface);
  box-shadow: var(--pasty-shadow-sm);
  transition: margin var(--pasty-t-fast) var(--pasty-ease);
}

.settings__switch[aria-checked="true"] .settings__knob {
  margin-inline-start: 19px;
}

.settings__choices {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.settings__choice {
  display: flex;
  align-items: center;
  gap: var(--pasty-space-2);
  width: 100%;
  min-height: var(--pasty-control-md);
  padding: var(--pasty-space-1) var(--pasty-space-2);
  border: 0;
  border-radius: var(--pasty-radius-sm);
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: start;
  cursor: pointer;
}

.settings__choice:hover {
  background: var(--pasty-hover);
}

/* The same check mark the menu rows use, for the same reason: one visual
   language for "this is the one in effect". */
.settings__choice::before {
  content: "";
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  background-color: currentcolor;
  opacity: 0;
  mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m5 12.5 4.5 4.5L19 7.5" fill="none" stroke="black" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>');
  mask-repeat: no-repeat;
  mask-position: center;
}

.settings__choice[aria-checked="true"]::before {
  opacity: 1;
}

.settings__choice[aria-checked="true"] {
  color: var(--pasty-text);
}

/* ---------- app header (editor pages) ---------- */

.editor-page {
  min-height: 100vh;
}

/* The band spans the window; its contents do not. */
.app-header {
  position: sticky;
  top: 0;
  z-index: 30;
  display: block;
  height: var(--pasty-header-height);
  padding-inline: var(--pasty-rail-gutter);
  background: var(--pasty-chrome);
}

/* THE RAIL. Deliberately the same construct as `.pasty-page` — width 100%, the
   same max-width, auto inline margins, inside the same gutter — so the chrome's
   edges land on the sheet's edges at every viewport width by definition, with
   nothing to compute and nothing to drift. The toolbar strip uses it too.
   Centring was never the problem: the toolbar was already centred on the sheet
   and still read as unrelated, because only edges are legible as alignment. */
.app-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--pasty-space-4);
  width: 100%;
  max-width: var(--pasty-page-max-width);
  height: 100%;
  margin-inline: auto;
}

.app-header__left,
.app-header__right {
  display: flex;
  align-items: center;
  gap: var(--pasty-space-2);
  min-width: 0;
}

/* Equal columns, not `space-between` alone: the left group is the only thing on
   the rail that grows, so it would swallow the free space and leave the keycap
   flush against the account controls. Two columns of the same size put it on
   the true centre, at every width it is shown at. */
.app-header__left {
  flex: 1 1 0;
}

/* `min-width` so an equal share is a floor, not a ceiling: these controls are
   `nowrap`, and a column narrower than they are would spill them leftwards over
   the cue. If a platform's UI font ever sets them wider than half the rail, the
   column wins and the cue slides off centre — off centre beats overlapping. */
.app-header__right {
  flex: 1 1 0;
  justify-content: flex-end;
  min-width: max-content;
  gap: var(--pasty-space-1);
}

/* Blue was the focal action's colour, and the wordmark isn't the action. */
.brand {
  flex: 0 0 auto;
  padding: 0 var(--pasty-space-1);
  /* Optical: sit the wordmark's glyphs on the rail, not its padding box. */
  margin-inline-start: calc(-1 * var(--pasty-space-1));
  color: var(--pasty-text);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.005em;
  text-decoration: none;
}

/* The title is document metadata — a filename, not a heading. Fixed basis so
   it renders at a readable width instead of collapsing to its content. */
#doc-title-slot {
  flex: 0 1 400px;
  min-width: 0;
}

/* The shared page's title: the same metadata register as the editor's title
   field, but static text — a viewer is told the name, never handed it. */
.shared-title {
  min-width: 0;
  overflow: hidden;
  padding: 0 var(--pasty-space-1);
  color: var(--pasty-text-secondary);
  font-size: var(--pasty-text-sm);
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------- command palette cue ---------- */

/* The header's third flex item, between the two groups, and the whole of what
   the chrome says about the palette. Server-rendered hidden; palette.ts unhides
   it, so a browser with no palette keeps the two-group header it had.

   The button is a hit area around the caps rather than a control in its own
   right: no border, no fill, no words — nothing to see but the keys you would
   have pressed. */
.palette-cue {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  height: var(--pasty-control-md);
  padding: 0 var(--pasty-space-2);
  border: 0;
  border-radius: var(--pasty-radius-md);
  background: transparent;
  cursor: pointer;
}

/* ---------- keycaps ---------- */

/* A chord is drawn as one cap per key — `⌘` `⇧` `C` — inside one <kbd>: the
   header cue, the palette's rows and the menu's hint all use it, from one
   rule. Each cap is a fill, a hairline and a one-pixel bottom lip; pressing
   the cue removes the lip and moves the caps down onto it. <kbd> defaults to
   monospace, which is right for the letters and digits; the modifier and
   arrow glyphs take the UI face, where they are drawn at a size that
   matches. */
.kbd {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-family: var(--pasty-mono);
}

.kbd__key {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 var(--pasty-space-1);
  border: 1px solid var(--pasty-key-border);
  border-radius: 4px;
  background: var(--pasty-key-fill);
  box-shadow: inset 0 -1px 0 var(--pasty-key-lip);
  color: var(--pasty-key-text);
  font-family: var(--pasty-mono);
  font-size: 10.5px;
  font-weight: 500;
  line-height: 1;
  transition:
    color var(--pasty-t-fast) var(--pasty-ease),
    border-color var(--pasty-t-fast) var(--pasty-ease),
    box-shadow var(--pasty-t-fast) var(--pasty-ease),
    transform var(--pasty-t-fast) var(--pasty-ease);
}

.kbd__key--glyph {
  font-family: var(--pasty-ui-font);
  font-size: 12px;
}

.palette-cue:hover .kbd__key {
  border-color: var(--pasty-border);
  color: var(--pasty-text);
}

.palette-cue:active .kbd__key {
  box-shadow: none;
  transform: translateY(1px);
}

.logout-form {
  margin: 0;
}

/* ---------- account menu ---------- */

.account-menu__trigger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--pasty-control-sm);
  height: var(--pasty-control-sm);
  margin-left: var(--pasty-space-1);
  border-radius: 50%;
  background: var(--pasty-fill-quiet);
  color: var(--pasty-text-muted);
  font-size: var(--pasty-text-sm);
  font-weight: 600;
  text-transform: uppercase;
  cursor: pointer;
  transition:
    background-color var(--pasty-t-fast) var(--pasty-ease),
    color var(--pasty-t-fast) var(--pasty-ease);
}

.account-menu__trigger:hover,
.account-menu[open] > .account-menu__trigger {
  background: var(--pasty-fill-quiet-strong);
  color: var(--pasty-text);
}

/* ---------- auth pages ---------- */

.auth-shell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--pasty-space-5);
  min-height: 100vh;
  padding: 64px var(--pasty-space-5);
}

.auth-brand {
  color: var(--pasty-text);
  font-size: var(--pasty-text-xl);
  font-weight: 600;
  letter-spacing: -0.01em;
  text-decoration: none;
}

.auth-card {
  width: 100%;
  max-width: 400px;
  padding: var(--pasty-space-7);
  background: var(--pasty-surface);
  border: 1px solid var(--pasty-border-soft);
  border-radius: var(--pasty-radius-lg);
  box-shadow: var(--pasty-shadow-sm);
}

.auth-title {
  margin: 0 0 var(--pasty-space-2);
  font-size: var(--pasty-text-xl);
  font-weight: 600;
  letter-spacing: -0.01em;
}

.auth-intro {
  margin: 0 0 var(--pasty-space-5);
  color: var(--pasty-text-muted);
}

.auth-links {
  margin: var(--pasty-space-4) 0 0;
  font-size: var(--pasty-text-sm);
}

.auth-footnote {
  margin: 0;
  color: var(--pasty-text-muted);
  font-size: var(--pasty-text-sm);
}

.field {
  margin-bottom: var(--pasty-space-4);
}

.field label {
  display: block;
  margin-bottom: var(--pasty-space-1);
  font-size: var(--pasty-text-sm);
  font-weight: 500;
}

/* Broad enough that a form field added later inherits the system instead of
   falling back to the user agent. */
.field input,
.field select,
.field textarea {
  width: 100%;
  height: var(--pasty-control-lg);
  padding: 0 var(--pasty-space-3);
  border: 1px solid var(--pasty-border);
  border-radius: var(--pasty-radius-md);
  font: inherit;
  font-size: var(--pasty-text-md);
  background: var(--pasty-surface);
  color: var(--pasty-text);
  transition:
    border-color var(--pasty-t-fast) var(--pasty-ease),
    box-shadow var(--pasty-t-fast) var(--pasty-ease);
}

.field textarea {
  height: auto;
  padding: var(--pasty-space-2) var(--pasty-space-3);
}

.field input:focus,
.field select:focus,
.field textarea:focus {
  border-color: var(--pasty-accent);
  outline: none;
  box-shadow: 0 0 0 3px var(--pasty-focus-ring);
}

.field--invalid input {
  border-color: var(--pasty-danger);
}

.field__help {
  margin: var(--pasty-space-1) 0 0;
  color: var(--pasty-text-muted);
  font-size: var(--pasty-text-xs);
}

.field__help ul {
  margin: var(--pasty-space-1) 0 0;
  padding-left: 18px;
}

.field__error {
  margin: var(--pasty-space-1) 0 0;
  color: var(--pasty-danger);
  font-size: var(--pasty-text-xs);
}

/* ---------- CLI token page ---------- */

/* What the credential can do, said where it is minted. Muted and small rather
   than in the danger palette: this is the scope of a thing being created, not
   an error about one — but `delete` is bolded inside it, because that is the
   part that cannot be taken back. */
.token-scope {
  margin: 0 0 var(--pasty-space-4);
  color: var(--pasty-text-muted);
  font-size: var(--pasty-text-sm);
}

.token-reveal {
  margin-bottom: var(--pasty-space-4);
  padding: var(--pasty-space-3);
  background: var(--pasty-accent-soft);
  border: 1px solid var(--pasty-accent-active);
  border-radius: var(--pasty-radius-md);
}

.token-reveal__value {
  display: block;
  padding: var(--pasty-space-2) var(--pasty-space-3);
  background: var(--pasty-surface);
  border: 1px solid var(--pasty-border-soft);
  border-radius: var(--pasty-radius-sm);
  font-family: var(--pasty-mono);
  font-size: var(--pasty-text-sm);
  overflow-wrap: anywhere;
  user-select: all;
}

.token-reveal__note {
  margin: var(--pasty-space-1) 0;
  font-size: var(--pasty-text-sm);
}

.token-meta {
  margin: 0 0 var(--pasty-space-4);
  font-size: var(--pasty-text-sm);
}

.token-meta div {
  display: flex;
  justify-content: space-between;
  padding: var(--pasty-space-1) 0;
}

.token-meta dt {
  color: var(--pasty-text-muted);
}

.token-meta dd {
  margin: 0;
}

/* Every code chip on an auth page, except the token itself — which is a block
   the user is meant to select whole, and has its own treatment above. */
.auth-card code:not(.token-reveal__value) {
  padding: 1px 5px;
  border-radius: var(--pasty-radius-sm);
  background: var(--pasty-surface-sunken);
  font-family: var(--pasty-mono);
  font-size: 0.9em;
}

/* One error palette, shared with the editor's save-problem note. */
.form-errors {
  margin-bottom: var(--pasty-space-4);
  padding: var(--pasty-space-3);
  border: 1px solid var(--pasty-danger-border);
  border-radius: var(--pasty-radius-md);
  background: var(--pasty-danger-soft);
  color: var(--pasty-danger);
  font-size: var(--pasty-text-sm);
}

.form-errors p {
  margin: 0;
}

/* ---------- narrow screens ----------
   Desktop is the priority. What survives here is the loop itself: the document
   and its title. */

/* Edge-to-edge below this point: the sheet loses its side borders, so there is
   no longer an edge to align to. Chrome keeps a small gutter because text
   touching the window edge reads as broken. */
@media (max-width: 900px) {
  :root {
    --pasty-rail-gutter: var(--pasty-space-2);
  }
}

@media (max-width: 720px) {
  /* The title takes what's left rather than reserving a fixed column. */
  #doc-title-slot {
    flex: 1 1 auto;
  }

  /* Visually hidden rather than removed: the live region still announces every
     save, it just stops competing for pixels there aren't any of. */
  #save-status-slot {
    position: absolute;
    width: 1px;
    height: 1px;
    min-width: 0;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
  }

  /* Both auth links go, not just one: the anonymous banner carries a way in,
     and each auth page links to the other. Docs goes with them, since it is
     one more quiet link and not this page's action. What is left up here is the
     appearance trigger, which has nowhere else to live. The shared page's
     Copy Markdown is exempt: it is that page's one action, and nothing else
     on the page offers it. A docs page's Edit a copy is exempt for the same
     reason: it is the page's one verb. */
  .app-header__right > .btn--quiet:not(.shared-copy):not(.docs-edit) {
    display: none;
  }

  .auth-card {
    padding: var(--pasty-space-5);
  }
}

/* Past this point the title field is narrower than the word "Untitled", which
   reads as a broken control rather than a quiet one. The document and the loop
   around it still work; the filename waits for a wider screen. */
@media (max-width: 560px) {
  #doc-title-slot {
    display: none;
  }

  /* This narrow is almost always a touch screen: a keycap teaching a keyboard
     chord is noise there, and the menu row still opens the palette. The same
     goes for the caps on the palette's rows. */
  .palette-cue,
  .palette__key {
    display: none;
  }
}

