/* Taskerator — design tokens that are consumed only by hand-written CSS
   (not by Tailwind utilities). The colour, typography, radius, and
   shadow tokens that back utilities live in
   app/assets/tailwind/application.css under @theme. This file is served
   as-is by Propshaft via stylesheet_link_tag :app. */

/* DM Sans, self-hosted from app/assets/fonts/. Both files are variable
   fonts covering the 400-700 weight range used by --font-sans. The
   unicode-range split lets the browser skip the latin-ext download for
   pages that don't need extended Latin glyphs. Propshaft fingerprints
   the url() references at build time. */
@font-face {
  font-family: "DM Sans";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/assets/dm-sans-latin-fe3ac7ee.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: "DM Sans";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/assets/dm-sans-latin-ext-c1985016.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;
}

:root {
  /* Layout dimensions (mirrors of the @theme width/height tokens for
     hand-written CSS that does not go through Tailwind). */
  --sidebar-width:    188px;
  --header-height:    48px;
  --toolbar-height:   40px;
  --bottombar-height: 64px;

  /* Row padding (density). Mobile rows are taller for touch targets;
     desktop tightens up. */
  --row-py-mobile:  11px;
  --row-py-desktop: 7px;
}

/* ── Component utility classes ───────────────────────────────────────
   These are component-style classes, not single-property utilities,
   so they live here rather than in @theme. They reference the colour
   tokens emitted by @theme (var(--color-p), var(--color-n100), etc.). */

/* iOS Safari zooms the page whenever a focused form control renders below 16px,
   and it never zooms back out. Once zoomed, the visual viewport stops matching
   the layout viewport, so position:fixed chrome - the task sheet and the bottom
   bar - drifts with the scroll instead of staying put. Raising the controls to
   16px removes the trigger at the source and leaves pinch-zoom available to
   anyone who wants it. These rules are unlayered, so they outrank the Tailwind
   text-* utilities the fields carry. */
@media (max-width: 1023px) {
  input:not([type="checkbox"]):not([type="radio"]),
  textarea,
  select {
    font-size: 16px;
  }
}

/* Due date pill. */
.due-pill {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 11px;
  font-weight: 500;
  padding: 2px 7px;
  border-radius: 20px;
  background: var(--color-n100);
  color: var(--color-n600);
  border: 1px solid var(--color-n200);
  white-space: nowrap;
  flex-shrink: 0;
}

.due-pill.today {
  background: var(--color-warn-lt);
  color: var(--color-warn);
  border-color: #fde68a;
}

.due-pill.overdue {
  background: var(--color-ng-lt);
  color: var(--color-ng);
  border-color: #f5c2c7;
}

/* Section header. */
.section-hd {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 8px 16px 4px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  color: var(--color-n500);
}

.section-badge {
  background: var(--color-n200);
  color: var(--color-n600);
  font-size: 9px;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: 8px;
}

/* Separators between the rows of a Today section. They follow from the rows'
   order rather than being written into each row, so a row the offline queue adds
   or moves leaves them right without anything having to redraw them. */
.today-rows > .task-row + .task-row {
  border-top: 1px solid var(--color-n100);
}

/* Separators between the rows of one day in the List view, for the same reason as
   the Today rows above: a row prepended by a broadcast or by the offline queue
   arrives on its own, and a separator written into the markup between rows would
   be missing from above it. A date header between two rows breaks the adjacency, so
   days stay divided by their headers alone. The fallback color covers a build of
   Tailwind that no longer emits the variable once nothing else uses gray-200. */
.todo-list-rows > li[data-created-date] + li[data-created-date] {
  border-top: 1px solid var(--color-gray-200, oklch(92.8% 0.006 264.531));
}

/* Active card outline for the FVP chain card. */
.chain-card-active {
  box-shadow: 0 2px 12px rgba(0, 102, 204, 0.07), 0 0 0 1.5px var(--color-p);
  border-radius: 14px;
  background: #fff;
  overflow: hidden;
}

/* The chain card's items. Each carries the markup for being worked on and the
   compact markup a queued or finished item uses, and its data-chain-state picks
   which shows, so the offline queue can move an item between the three by changing
   one attribute. The separators follow the items' order, as on the Today rows. */
.chain-item + .chain-item {
  border-top: 1px solid var(--color-n100);
}

.chain-item:not([data-chain-state="active"]) > .chain-item-active,
.chain-item[data-chain-state="active"] > .chain-item-compact,
.chain-item[data-chain-state="done"] .chain-item-queued-mark,
.chain-item:not([data-chain-state="done"]) .chain-item-done-mark {
  display: none;
}

.chain-item-compact {
  padding: 9px 16px;
  color: var(--color-n500);
}

.chain-item[data-chain-state="done"] {
  opacity: 0.38;
}

.chain-item[data-chain-state="done"] .chain-item-compact {
  padding: 8px 16px;
  color: var(--color-n600);
}

.chain-item[data-chain-state="done"] .chain-item-title {
  text-decoration: line-through;
}

/* Task checkbox. */
.task-cb {
  width: 16px;
  height: 16px;
  border-radius: 4px;
  border: 1.5px solid var(--color-n300);
  background: transparent;
  flex-shrink: 0;
  cursor: pointer;
  transition: all 0.15s;
  display: flex;
  align-items: center;
  justify-content: center;
}

.task-cb.checked {
  background: var(--color-ok);
  border-color: var(--color-ok);
}

/* "Working on" label (chain anchor item in the Today view chain card). */
.working-on-badge {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.9px;
  text-transform: uppercase;
  color: var(--color-p);
  background: var(--color-p-lt);
  padding: 2px 7px;
  border-radius: 3px;
  display: inline-block;
}

/* "Now" tag for the focus-mode active card. Shares the working-on-badge
   palette but uses a slightly larger pill so it reads as the focal point
   on a single-task screen rather than as a sibling label inside a row. */
.now-tag {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--color-p);
  background: var(--color-p-lt);
  padding: 3px 9px;
  border-radius: 6px;
  display: inline-block;
}

/* Base normalization.

   Tailwind's preflight is disabled (see app/assets/tailwind/application.css), so
   nothing here normalizes native elements. The previous component kit shipped its
   own native-element stylesheet and was quietly providing this; when it was
   removed the body fell back to the browser's default serif and layout lists got
   their user-agent indent back. These rules restore exactly what was lost, and no
   more — they are not a normalize.css.

   The alternative is to re-enable preflight now that there is no kit to conflict
   with. That is a deliberate restyle rather than a cleanup: it would also change
   box-sizing, heading sizes, and button chrome across every view, and the markup
   was authored against preflight being off. */
:root {
  /* The canonical body font stack. Tailwind's @theme carries the same value as
     --font-sans, but Tailwind 4 only emits theme variables that a utility
     actually uses, and nothing uses font-sans, so it never reaches the browser.
     app/assets/stylesheets/ui5.css points UI5's --sapFontFamily at this. */
  --font-body: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

/* Every layout in this app is written assuming border-box, which is the usual
   Tailwind assumption. Preflight would normally supply it but is deliberately off
   (see app/assets/tailwind/application.css), and without it padded containers
   overflow their parents: the page container alone pushed the viewport 32px wide
   and put a horizontal scrollbar on every screen. */
*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  font-family: var(--font-body);
  color: var(--color-n900);
}

/* The hidden attribute has to beat display utilities such as `flex`, which is what
   preflight's `[hidden] { display: none !important }` would do. Server-rendered
   views and Stimulus controllers toggle `hidden` to show and hide rows, so the
   attribute must win regardless of the element's own display value. */
[hidden] {
  display: none !important;
}

/* Layout lists carry no user-agent indent or markers. Rendered markdown in a note
   is the one place that wants them, so it opts back in. */
ul,
ol {
  margin-block: 0;
  padding-inline-start: 0;
}

.prose ul,
.prose ol {
  margin-block: revert;
  padding-inline-start: revert;
  list-style: revert;
}

/* Row inside the focus-mode "Up next" queue. Rolling the row layout into a
   single hand-written class keeps it unlayered, which beats Tailwind's
   utilities layer, and pins the touch-target height we need on mobile.

   This originally existed to outrank a cascade layer WebAwesome declared after
   Tailwind's utilities. That layer is gone, so the class could now be expressed
   as utilities; it is left as is because the browser's own <li> styling still
   applies with preflight disabled. */
.focus-queue-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  margin: 0;
  font-size: 14px;
  line-height: 1.4;
  color: var(--color-n700);
}

/* Safari gives a date input an intrinsic minimum width wider than the panel that
   holds it, and width:100% cannot shrink below it, so the field ran off the right
   edge while the note textarea beside it did not. It also draws no field
   background of its own, which over the panel's grey left it reading as an empty
   block rather than something to tap. */
.sheet-date-input {
  appearance: none;
  -webkit-appearance: none;
  min-width: 0;
  max-width: 100%;
  /* Matches the toolbar buttons, so the row is tappable at the same size. */
  min-height: 44px;
}

/* The sheet's action toolbar is the last row of a sheet pinned to the bottom
   edge, so on a phone with a home indicator its buttons would otherwise sit in
   the gesture area. */
.sheet-toolbar {
  padding-bottom: calc(0.5rem + env(safe-area-inset-bottom));
}

/* Quick-entry sheet's toolbar toggles. Active means "this field is set, or its
   panel is open" - the tinted chip is what makes a due date set and then collapsed
   still visible in the toolbar.

   It carries its own chrome reset rather than pairing with .bare-button. That
   class is declared further down this file, so at equal specificity it wins, and
   its justify-content: flex-start and border-radius: 0 - which are right for the
   inline text containers it exists for - turned these into hard squares with the
   icon shoved against the left edge. */
.sheet-tool {
  /* 44px is Apple's minimum touch target. The glyph inside stays 16px; only the
     hit area grows, and the desktop pointer does not need the same slack. */
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  border-radius: 6px;
  color: var(--color-n500);
  cursor: pointer;
  transition: background 0.13s, color 0.13s;
}

.sheet-tool:hover {
  background: var(--color-n100);
}

@media (min-width: 1024px) {
  .sheet-tool {
    width: 32px;
    height: 32px;
  }
}

.sheet-tool.active {
  background: var(--color-p-lt);
  color: var(--color-p);
}

.sheet-tool.active-warn {
  background: var(--color-warn-lt);
  color: var(--color-warn);
}

/* Quick-entry sheet's metadata pills. One per field that has a value, sitting under
   the title so nothing the user set can be hidden by a collapsed panel. */
.meta-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font: inherit;
  font-size: 11px;
  font-weight: 500;
  padding: 3px 8px;
  border-radius: 20px;
  background: var(--color-n100);
  color: var(--color-n600);
  border: 1px solid var(--color-n200);
  white-space: nowrap;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
}

/* A pill paired with its dismiss button. Only the due pill uses one, and only when
   the date was read out of the title. */
.meta-pill-group {
  display: inline-flex;
  align-items: center;
  gap: 3px;
}

.meta-pill-dismiss {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  padding: 0;
  border: 1px solid var(--color-n200);
  border-radius: 50%;
  background: var(--color-n100);
  color: var(--color-n600);
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
}

.meta-pill-dismiss:hover {
  background: var(--color-n200);
}

/* tokens.css loads after Tailwind's utilities, so the display above would outrank
   .hidden at equal specificity and a pill with no value would still take up space
   as an empty chip. */
.meta-pill.hidden,
.meta-pill-group.hidden,
.meta-pill-dismiss.hidden {
  display: none;
}

.meta-pill.is-brand {
  background: var(--color-p-lt);
  color: var(--color-p);
  border-color: var(--color-p-lt);
}

.meta-pill.is-warn {
  background: var(--color-warn-lt);
  color: var(--color-warn);
  border-color: #fde68a;
}

.meta-pill.is-overdue {
  background: var(--color-ng-lt);
  color: var(--color-ng);
  border-color: #f5c2c7;
}

/* Quick-pick chip used in the sheets: due dates, and the quick-entry sheet's
   profile picker. */
.due-chip,
.sheet-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  font-weight: 500;
  padding: 5px 11px;
  border-radius: 14px;
  background: var(--color-n100);
  color: var(--color-n700);
  border: 1px solid var(--color-n200);
  cursor: pointer;
  transition: background 0.13s, color 0.13s, border-color 0.13s;
}

.due-chip:hover,
.sheet-chip:hover {
  background: var(--color-n200);
}

.due-chip.active,
.sheet-chip.active {
  background: var(--color-p);
  color: var(--color-n0);
  border-color: var(--color-p);
}

/* Highlight applied to a todo row in the desktop split's "ALL TASKS"
   reference column when the row belongs to the active chain. The blue
   left border + tinted background pull the chain's members out of the
   surrounding list so users can see the shape of the chain without
   leaving the all-tasks view. */
.chain-row-highlight {
  background: var(--color-p-lt);
  box-shadow: inset 3px 0 0 var(--color-p);
  padding-left: 8px;
}

/* Toggle switch. */
.toggle-switch {
  width: 36px;
  height: 20px;
  border-radius: 10px;
  border: none;
  cursor: pointer;
  padding: 2px;
  display: flex;
  align-items: center;
  transition: background 0.2s;
  flex-shrink: 0;
}

.toggle-switch.on  { background: var(--color-p); }
.toggle-switch.off { background: var(--color-n300); }

.toggle-thumb {
  width: 16px;
  height: 16px;
  border-radius: 8px;
  background: #fff;
  transition: transform 0.2s;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}

.toggle-switch.on  .toggle-thumb { transform: translateX(16px); }
.toggle-switch.off .toggle-thumb { transform: translateX(0); }

/* Sidebar section heading — small uppercase label above each group. */
.sidebar-section {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  color: var(--color-n500);
  padding: 6px 10px 3px;
}

/* Desktop sidebar's new-task button. Full width under the wordmark, and the one
   capture affordance present in every desktop view. */
.sidebar-new-task {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 100%;
  padding: 7px 10px;
  border: 0;
  border-radius: 6px;
  background: var(--color-p);
  color: var(--color-n0);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  transition: background 0.13s;
}

/* There is no darker brand token, so the hover state darkens the one there is
   rather than introducing a second blue that nothing else uses. */
.sidebar-new-task:hover {
  filter: brightness(0.94);
}

/* List view's create row - its entry point into the quick-entry sheet. */
.create-row {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 10px 14px;
  border: 1px dashed var(--color-n300);
  border-radius: 10px;
  background: var(--color-n0);
  color: var(--color-p);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  transition: background 0.13s, border-color 0.13s;
}

.create-row:hover {
  background: var(--color-p-lt);
  border-color: var(--color-p);
}

/* Sidebar entry — a tappable row in the desktop sidebar or mobile drawer. */
.sidebar-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  border-radius: 6px;
  font-size: 13px;
  text-decoration: none;
  margin-bottom: 1px;
  transition: background 0.13s, color 0.13s;
}

.sidebar-item:hover {
  background: var(--color-n100);
}

  /* Tailwind preflight is disabled (see app/assets/tailwind/application.css)
   so the browser's native <button> chrome — ButtonFace background, system
   border, centred font, appearance: auto — bleeds through utilities like
   bg-transparent. .bare-button strips that chrome on the buttons we style
   ourselves. UI5's components live in shadow DOM and are not affected.

   The explicit display, justify-content, and height declarations below are
   still load-bearing: they make these buttons behave as inline text containers
   rather than as the inline-flex, centred, fixed-height boxes a user agent
   renders. */
.bare-button {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 0;
  border-radius: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  display: inline-flex;
  text-align: left;
  justify-content: flex-start;
  height: auto;
  white-space: normal;
}

/* The handle a row in a manually ordered list is dragged by. It is the only part of
   the row that starts a drag, so it has to be big enough to find with a thumb, and
   touch-action keeps the browser from scrolling the page instead of dragging. A row
   that cannot be dragged keeps an empty handle so its checkbox lines up. */
.drag-handle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  align-self: stretch;
  flex-shrink: 0;
  color: var(--color-n400);
}

.drag-handle[data-sortable-handle] {
  cursor: grab;
  touch-action: none;
}

.sortable-offline .drag-handle[data-sortable-handle] {
  cursor: default;
  opacity: 0.4;
}

.sortable-ghost {
  opacity: 0.4;
}

/* button_to renders a <form> wrapper; flatten it so the inner button can be
   styled like a sidebar-item without inheriting form spacing. The button
   keeps the .sidebar-item layout (display:flex, padding) intact — only
   the browser chrome is reset. */
.sidebar-item-form {
  display: block;
  margin: 0;
}

.sidebar-item-form button.sidebar-item {
  appearance: none;
  -webkit-appearance: none;
  width: 100%;
  background: transparent;
  border: 0;
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: inherit;
  justify-content: flex-start;
}

/* Main content padding compensates for the fixed mobile chrome (header
   and bottom bar). On lg: viewports the chrome is hidden so the padding
   collapses. */
.layout-main {
  padding-top: var(--header-height);
  padding-bottom: calc(var(--bottombar-height) + env(safe-area-inset-bottom));
}

@media (min-width: 1024px) {
  .layout-main {
    padding-top: 0;
    padding-bottom: 0;
  }
}

/* The chain strip flows edge-to-edge inside the chain-mode list, so the
   default <ui5-panel> padding around the header and content needs to
   collapse. We do it via ::part() so the override targets the
   component's shadow DOM directly. */
ui5-panel.todo-chain-strip::part(header) {
  padding: 0.5rem 1rem;
}

ui5-panel.todo-chain-strip::part(content) {
  padding: 0;
}

/* Native date and datetime inputs.

   The design deliberately keeps these native rather than adopting a kit date
   picker (quick-pick chips plus <input type="date">), which leaves them with no
   component to inherit styling from. WebAwesome's native.css used to supply it
   silently, including a width: 100% on every text-accepting input, which is why
   these stretched to the full column. Styling them here states the treatment
   explicitly and keeps them sized like the UI5 fields they sit beside. */
.date-input {
  width: 11rem;
  max-width: 100%;
  height: 30px;
  padding: 0 0.625rem;
  font: inherit;
  font-size: 13px;
  color: var(--color-n900);
  background: var(--color-n0);
  border: 1px solid var(--color-n300);
  border-radius: var(--radius-md);
  outline: none;
}

.date-input:hover {
  border-color: var(--color-n400);
}

.date-input:focus {
  border-color: var(--color-p);
}

/* ── Connection state, the transitional band, and the toast ──────────
   Offline is a state, not an error, so everything here is calm: one colour pair
   per state, one spinner in the whole flow, and no blocking. The pairs are the
   design tokens rather than new colours — slate is the neutral n200/n700, syncing
   the brand p-lt/p, synced ok-lt/ok, and failed ng-lt/ng — so a state here reads
   the same as the same state anywhere else in the app. */

/* The mobile header's status pill and the desktop sidebar's status row share a
   shape and differ only in how they sit: the pill is a chip beside the settings
   button, the row is a full-width line above Settings. */
.conn-pill,
.conn-row {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1;
  border-radius: 999px;
  padding: 4px 9px;
  text-decoration: none;
  white-space: nowrap;
}

.conn-row {
  display: flex;
  width: 100%;
  border-radius: var(--radius-md);
  padding: 6px 8px;
  font-weight: 500;
}

/* Online on the desktop sidebar is one quiet line of reassurance, so it is the
   only state without a fill behind it. The mobile pill has no online state at
   all; connected is the default and is not decorated. */
.conn-slate  { background: var(--color-n200); color: var(--color-n700); }
.conn-brand  { background: var(--color-p-lt); color: var(--color-p); }
.conn-ok     { background: var(--color-ok-lt); color: var(--color-ok); }
.conn-bad    { background: var(--color-ng-lt); color: var(--color-ng); }
.conn-quiet  { background: transparent; color: var(--color-n500); }

/* The one spinner in the whole flow, and it turns only while a drain is actually
   sending. Everywhere else the queue's count stands in for progress: it says what
   is owed rather than that the app is busy. */
.conn-spinning {
  animation: conn-spin 1.1s linear infinite;
}

@keyframes conn-spin {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .conn-spinning { animation: none; }
}

/* A Settings entry that leads somewhere only the network can serve. The
   affordance stays where it is and says why rather than disappearing, which is
   what keeps the chrome from rearranging itself every time a train enters a
   tunnel. */
.offline-restricted {
  opacity: 0.45;
  pointer-events: none;
}

.offline-chip {
  display: none;
  margin-left: auto;
  font-size: var(--text-2xs);
  font-weight: 600;
  line-height: 1;
  border-radius: 999px;
  padding: 2px 6px;
  background: var(--color-n200);
  color: var(--color-n700);
}

.offline-restricted .offline-chip {
  display: inline-block;
}

/* The transitional band, under the chrome and above the content. It appears on
   three transitions only and never on a steady state; the pill and the sidebar
   row carry the state from then on. */
.offline-band {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  font-size: var(--text-sm);
  line-height: 1.4;
}

.offline-band-slate { background: var(--color-n100); color: var(--color-n700); }
.offline-band-brand { background: var(--color-p-lt);  color: var(--color-p); }
.offline-band-bad   { background: var(--color-ng-lt); color: var(--color-ng); }

.offline-band-dismiss {
  background: none;
  border: 0;
  padding: 2px;
  margin-left: auto;
  color: inherit;
  cursor: pointer;
  line-height: 0;
}

/* The dark bottom toast. One at a time, dismissed after a few seconds. It sits
   above the bottom bar on mobile, where that bar and the home indicator both
   occupy the bottom edge, and in the bottom-right corner on desktop. */
.app-toast {
  position: fixed;
  z-index: 60;
  left: 16px;
  right: 16px;
  bottom: calc(var(--bottombar-height) + 12px + env(safe-area-inset-bottom));
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 14px;
  border-radius: var(--radius-lg);
  background: var(--color-n900);
  color: var(--color-n0);
  font-size: var(--text-base);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 180ms ease, transform 180ms ease;
  pointer-events: none;
}

.app-toast.is-visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.app-toast-action {
  margin-left: auto;
  flex-shrink: 0;
  font-weight: 600;
  color: var(--color-p-lt);
  text-decoration: none;
}

@media (min-width: 1024px) {
  .app-toast {
    left: auto;
    right: 20px;
    bottom: 20px;
    max-width: 22rem;
  }
}

/* A row whose completion is queued. The plan's rule is that rows are otherwise
   untouched offline, so this is only the completed treatment the row would have
   had anyway, applied early: the tick stays ticked and the title reads as done.
   It is written against the row container rather than against each row's own
   markup because the three shapes that can be completed -- the list row, the
   Today row, and the chain card's anchor -- style their titles differently and
   only the container is common to all three. */
.outbox-completed {
  opacity: 0.42;
}

.outbox-completed [data-task-sheet-url-param],
.outbox-completed [data-outbox-row-title] {
  text-decoration: line-through;
}
