/* Typing in the composer filters the list, so the page can shrink below one
   viewport mid-word and the classic scrollbar vanishes, shifting the whole
   layout sideways between keystrokes. Reserving the gutter keeps the column
   still; it also holds the width when the actions sheet locks the page. */
html{background:var(--sk-color-canvas);scrollbar-gutter:stable}
body{min-width:20rem}
/* A slightly smaller shared gutter on a wide screen. The UI package sets 2rem there for
   every application, which is the right rhythm for a page of prose and too
   much air for a list read against a fixed sidebar a rem away — and a page
   carrying an hour already reserves 3.6rem more on top of it.

   The token rather than .sk-page's padding, because the composer bleeds out by
   exactly one gutter and pads back in by one to cover the strip a row would
   otherwise show through; move one without the other and it hangs outside the
   page. Here rather than in the UI package, because that token is shared with
   seven other applications, six of them pinned versions behind, and they would
   inherit a layout change nobody reviewed the moment they bumped. */
@media(min-width:48rem){:root{--sk-gutter:1.5rem}}
/* And the list's own measure, which is the other half of that distance. The
   UI package's reading width is 56rem, and a column that narrow floats in the
   middle of the space beside the sidebar: at 1728px it left 272px of nothing
   on either side of it, which is where the gap was actually coming from. A
   wider measure leaves less to split, so the column moves back toward the
   panel without being pinned to it.

   Only the two pages that are a list with a composer on them. Settings and the
   workspace form stay at the reading width, where 56rem is the point. */
/* Human review found 72rem too close to the sidebar. Pull each edge inward
   by 2rem at wide widths while retaining the wider-than-reading measure. */
.sk-page--narrow.sk-page--action-bar{--sk-page-width:68rem}
/* The page wrapper, the heading ramp, the interstitial and the empty state now
   come from .sk-page, .sk-page-heading, .sk-auth-page and .sk-empty in the UI
   package. What is left in this file is what is genuinely YAT's: the composer,
   the todo row, and the two overlays that hang off it. */
/* The composer is the app's primary action, so on a phone it sits at the
   bottom edge in thumb reach rather than at the top of a list that scrolls
   away. It was a fixed .sk-action-bar held down by a keyboard inset yat.js
   measured off visualViewport, which took it out of the page's flow: anything
   that changed what the fixed bar was positioned against — a rotation, a
   software keyboard, an ancestor that happened to establish a containing
   block — detached it from that edge and it scrolled off with the list. It is
   a sticky footer now. The page becomes a column below 48rem and the form is
   ordered last in it, so it rides the bottom of the screen while the list
   scrolls behind it, is the last thing on the page at the end of the scroll,
   and needs no reserved strip because it is in the flow rather than over it.
   .sk-action-bar unpins itself at 48rem, where this becomes an ordinary row
   above the list again. */
/* The syntax caption is a wrapped flex line rather than a sibling of the form,
   so it stays under the field in both layouts — including inside the pinned
   bar on a phone. It is always in the markup, which is what keeps the row
   still while the first character is typed. */
.yat-composer{display:flex;flex-wrap:wrap;column-gap:.65rem;row-gap:.35rem}
.yat-composer>.yat-date-control{order:-1}
.yat-composer__submit-label{display:none}
.yat-composer__hint{order:1;flex-basis:100%;margin:0;color:var(--sk-color-text-muted);font-size:.72rem;line-height:1.15}
.yat-composer__hint code{padding:0 .15rem;border-radius:var(--sk-radius-sm);background:var(--sk-color-active);font-family:var(--sk-font-mono,ui-monospace,monospace);font-size:.75rem}
@media(min-width:48rem){.yat-composer{margin-bottom:1.75rem}.yat-composer>.yat-date-control{order:0}.yat-composer__submit-label{display:inline}
/* The composer follows the list down. It is the field that adds a task and,
   above this width, the field that searches — so scrolling away from it is
   scrolling away from both, and it is the long lists that need either.
   The page is what scrolls (.sk-main and .sk-page set no overflow), so `top`
   is measured against the viewport and no wrapper is needed. Canvas rather
   than surface, because rows are surface and a transparent bar with rows
   sliding under it is the one way this can look broken. The negative inline
   margin with the padding put back is what covers the gutter, where a row
   would otherwise show through at the edges. */
.yat-composer.sk-action-bar{position:sticky;top:var(--sk-safe-top,0);z-index:20;margin-inline:calc(var(--sk-gutter)*-1);padding:var(--sk-space-3) var(--sk-gutter);background:var(--sk-color-canvas)}
/* Both panels open downward up here. They open upward on a phone because the
   composer is pinned to the bottom edge; parked at the top of the scrollport
   an upward panel opens off the screen entirely. */
.yat-composer .yat-smart-suggestions{inset:calc(100% + .35rem) 3.5rem auto 0}
.yat-composer .yat-date-control__panel{inset:calc(100% + .45rem) auto auto 0}}
/* One field beside one button, the same everywhere it appears: the checklist,
   messages, labels, invitations, a workspace's name and shortcut. The field
   takes the room, the button stands beside it at the field's own height, and
   the pair stays on one line. The text is 1rem because anything smaller makes
   iOS zoom the page when the field is focused. Enter submits a single line, so
   none of them spells a shortcut out; only a multi-line note, where Enter is a
   new line, says ⌘ Enter.

   The composer is the same pair at the large size its bar gives its button. */
.yat-pair{display:flex;flex-wrap:nowrap;align-items:center;gap:.5rem}
.yat-pair>input:not([type=hidden]),.yat-composer>input{flex:1;min-width:0;height:var(--sk-size-control);padding:0 .85rem;border:1px solid var(--sk-color-border);border-radius:var(--sk-radius-md);background:var(--sk-color-surface);color:inherit;font:inherit;font-size:1rem}
.yat-pair>.sk-button,.yat-pair>.yat-message__cancel{flex:none;width:auto;height:var(--sk-size-control);min-height:0}
.yat-composer>input{height:var(--sk-size-control-lg)}
.yat-composer__submit[data-yat-loading=true]::before{width:1rem;height:1rem;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;content:"";animation:yat-spin .65s linear infinite}.yat-composer__submit[data-yat-loading=true]>.sk-icon{display:none}@keyframes yat-spin{to{transform:rotate(360deg)}}
@media(max-width:47.999rem){
/* The column that the order below is expressed in. The page is a block
   everywhere else; here it stacks its own children so the composer can be sent
   to the end of them without moving in the markup, where it belongs above the
   list for the wide layout and for reading order. */
.sk-page--action-bar{display:flex;flex-direction:column;padding-bottom:0}
/* Pinned by the page rather than to the window: sticky offsets are measured
   from the scrollport, so the software keyboard cannot leave the bar under
   itself, and the negative gutter is what keeps it edge to edge inside a page
   that is padded. */
.yat-composer.sk-action-bar{position:sticky;z-index:19;order:99;inset:auto auto 0 auto;margin-block-start:auto;margin-inline:calc(var(--sk-gutter)*-1);padding-bottom:max(var(--sk-space-3),var(--sk-safe-bottom))}
/* A sticky bar is held against the window only while its own box still runs
   below it, and the page's box stops where its content does. A list shorter
   than the screen therefore left the bar halfway up the window with the
   shell's empty ground beneath it — pinned in the only case where nothing
   needed pinning, and loose in the case a phone actually opens on. The page
   is made to fill the shell's screen-height main so that its bottom is the
   window's bottom whatever the list is holding, and the auto margin above the
   bar is what sends it down there: a sticky bottom offset only ever lifts a
   box that has fallen below the edge, never lowers one that has not reached
   it, so the page's spare height has to be spent before the bar rather than
   after it.

   The shell also keeps a rest of breathing room under the last row, which a
   bar ordered after that row inherits as a gap at the very end of the scroll.
   A page that ends in the bar has no last row to give air to, so it gives
   none. */
.sk-app-shell[data-mobile-menu=true] .sk-main:has(.sk-page--action-bar){display:flex;flex-direction:column;padding-bottom:0}
.sk-app-shell[data-mobile-menu=true] .sk-main>.sk-page--action-bar{flex:1}
.yat-rename-dialog.sk-modal{max-height:calc(var(--yat-visual-viewport-height,100dvh) - 1rem);margin:auto auto var(--yat-keyboard-inset,0px)}.yat-rename-dialog .sk-modal__surface{max-height:calc(var(--yat-visual-viewport-height,100dvh) - 1rem)}.yat-rename-dialog .sk-modal__body{overscroll-behavior:contain}.yat-rename-dialog .sk-button[type=submit]{position:sticky;bottom:0}}
/* On a phone the field takes the row when the magnifier opens it and the two
   filters sit beside it otherwise. Above 48rem the field is gone entirely — the
   composer is the search there — and only the filters are left in this row. */
.yat-search{display:flex;justify-content:space-between;align-items:center;gap:.75rem;margin:-.75rem 0 .75rem;color:var(--sk-color-text-muted)}.yat-search__field{display:flex;min-width:0;flex:1;align-items:center;gap:.4rem}.yat-search__actions{display:flex;flex:1;align-items:center;justify-content:flex-end;gap:.35rem}
/* Two groups with air between them. What narrows the list is on the left; what
   changes how the same list is drawn is on the right. Mixed into one run they
   all read as the same sort of switch, and pressing one to find out which was
   the only way to tell. */
.yat-search__filters,.yat-search__modes{display:flex;align-items:center;gap:.35rem}
.yat-search__modes{margin-left:auto}.yat-search input{width:100%;padding:.35rem .15rem;border:0;border-bottom:1px solid transparent;background:transparent;color:var(--sk-color-text);font-size:.82rem}.yat-search input::placeholder{color:color-mix(in srgb,var(--sk-color-text-muted) 70%,transparent)}.yat-search input:hover:not(:focus){border-bottom-color:var(--sk-color-border)}.yat-search input:focus,.yat-search input:focus-visible{border-color:transparent;outline:0;box-shadow:none}
/* The list filters are .sk-chip, quieted: they sit above the list rather than
   in it, so they are borderless until hovered and only fill in when pressed. */
.yat-filter-chip{min-height:var(--sk-size-touch);gap:.35rem;padding-inline:.55rem;border-color:transparent;background:transparent;color:var(--sk-color-text-muted);font-size:.75rem;font-weight:500;white-space:nowrap}.yat-filter-chip:hover{border-color:var(--sk-color-border);background:transparent;color:var(--sk-color-text)}
.yat-calendar-off{position:relative;display:inline-grid;place-items:center}.yat-calendar-off::after{content:"";position:absolute;top:50%;left:50%;width:1.5px;height:1.15rem;border-radius:999px;background:currentColor;transform:translate(-50%,-50%) rotate(-45deg)}
/* A deliberately substantial two-part control, like the reference: fixed
   meanings on each side, one continuous pill, and a filled selected half. */
.yat-view-switch{display:inline-flex;flex:none;overflow:hidden;border:1.5px solid var(--sk-color-text-muted);border-radius:999px;background:var(--sk-color-surface)}
.yat-view-switch button{display:grid;width:3.4rem;height:2.8rem;padding:0;place-items:center;border:0;background:transparent;color:var(--sk-color-text-muted);cursor:pointer}
.yat-view-switch button+button{border-left:1px solid var(--sk-color-text-muted)}
.yat-view-switch button:hover{background:var(--sk-color-active);color:var(--sk-color-text)}
.yat-view-switch button[aria-pressed=true]{background:color-mix(in srgb,var(--sk-color-accent) 22%,var(--sk-color-surface));color:var(--sk-color-text)}
.yat-view-switch button:focus-visible{position:relative;z-index:1;outline:2px solid var(--sk-color-focus);outline-offset:-3px}
.yat-search-empty{margin:1rem 0;text-align:center;color:var(--sk-color-text-muted);font-size:.85rem}
/* The funnel. Its panel hangs below the chip rather than above it: the filters
   sit at the top of the list, so there is nothing above them to open into. */
.yat-label-filter{position:relative;display:inline-flex}
.yat-label-filter__panel{position:absolute;z-index:50;inset:calc(100% + .4rem) 0 auto auto;display:grid;width:max-content;max-width:min(20rem,calc(100vw - 2rem));gap:.5rem;padding:.7rem;border:1px solid var(--sk-color-border);border-radius:var(--sk-radius-md);background:var(--sk-color-surface);box-shadow:var(--sk-component-shadow-panel)}
.yat-label-filter__panel[hidden]{display:none}
.yat-label-filter__options{display:flex;flex-wrap:wrap;gap:.35rem}
.yat-label-filter__note{margin:0;color:var(--sk-color-text-muted);font-size:.72rem}
.yat-label-filter__clear{justify-self:start;min-height:2.25rem;padding:0 .7rem;border:1px solid transparent;border-radius:999px;background:transparent;color:var(--sk-color-text-muted);font:inherit;font-size:.8rem;cursor:pointer}
.yat-label-filter__clear:hover{background:var(--sk-color-active)}
/* A funnel with something in it is the one chip on the row that has to look
   switched on, so it keeps its label where the others drop theirs. */
.yat-filter-chip[aria-pressed=true]{border-color:var(--sk-color-accent);background:var(--sk-color-accent);color:var(--sk-color-on-accent)}
@media(max-width:30rem){.yat-label-filter [data-yat-label-filter-copy]{display:none}
.yat-label-filter .yat-filter-chip[aria-pressed=true] [data-yat-label-filter-copy]{display:inline}}
.yat-undo-toast{display:flex;align-items:center;justify-content:space-between;gap:1rem}.yat-undo-toast>div{min-width:0}.yat-undo-toast strong{display:block}.yat-undo-toast p{overflow:hidden;margin:.2rem 0 0;color:var(--sk-color-text-muted);font-size:.85rem;text-overflow:ellipsis;white-space:nowrap}.yat-undo-toast .sk-button{min-height:2.25rem;padding-inline:.8rem}
.yat-todo-region{display:grid;gap:1.25rem}
/* The sum of every timer this workspace has ever run, under the list it is
   the sum of. Quiet: it is a fact about the page, not a heading on it. */
.yat-workspace-foot{margin-top:1.5rem;color:var(--sk-color-text-muted);font-size:.8rem;text-align:center}
.yat-tracked-total{margin:0;color:var(--sk-color-text-muted);font-size:.85rem}
.yat-todo-list{padding:0;margin:0;border:1px solid var(--sk-color-border);border-radius:var(--sk-radius-lg);background:color-mix(in srgb,var(--sk-color-surface) 84%,transparent);list-style:none;overflow:visible}
.yat-todo-list[data-empty=true]{border-color:transparent;background:transparent}
/* Two columns on a phone. Item actions stay out of the way until a long press;
   the third column and hover affordance are the desktop widening. */
/* pan-y leaves vertical scroll to the browser and horizontal movement to the
   swipe gesture below — the same trade the day-view drag used to need only in
   the day view, now needed everywhere a finger can carry a row sideways. */
.yat-todo{position:relative;display:grid;grid-template-columns:2.75rem minmax(0,1fr);align-items:center;gap:.4rem;min-height:4.5rem;padding:.65rem .3rem;padding-top:calc(.65rem + var(--yat-time-caption,0rem));border-bottom:1px solid var(--sk-color-border);cursor:pointer;-webkit-touch-callout:none;touch-action:pan-y}
@media(min-width:48rem){.yat-todo{grid-template-columns:2.75rem minmax(0,1fr) auto;padding-inline:.75rem}}
.yat-todo[data-waiting=true]{--yat-edge:color-mix(in srgb,var(--sk-color-text) 38%,transparent)}
.yat-todo[data-frozen=true]{--yat-edge:color-mix(in srgb,var(--sk-color-text-muted) 62%,transparent);background:color-mix(in srgb,var(--sk-color-surface-muted) 58%,transparent)}
.yat-todo[hidden],.yat-waiting[hidden],.yat-frozen[hidden],.yat-scheduled[hidden],.yat-archive[hidden]{display:none}
/* The running row. The tint is deliberately weak — a filled label chip sits on
   this row too, and a strong wash behind it would fight the one colour the
   visitor chose themselves — so the timer says which row it is loudly in one
   small place instead: a filled pill in the meta line, with the edge and the
   tint only confirming it. Both are drawn from the theme's success colour, so
   the treatment survives light and dark without being restated. */
.yat-todo[data-running=true]{--yat-edge:var(--sk-color-success);background:color-mix(in srgb,var(--sk-color-success) 9%,transparent)}
/* The coloured left edge of a waiting, frozen or running row is an overlay
   rather than a border-left, because a border cannot be rounded on its own:
   on the first row of the list the bar ran straight past the container's
   curve and squared off a corner the list means to round. Rounding the list
   away with overflow:hidden was the other option and is the one to avoid —
   the list is deliberately overflow:visible and sko-zwl was a bug caused by
   clipping this row. ::before is spoken for by the sort-mode grip, so this
   is ::after. Each state sets only --yat-edge; the geometry is stated once. */
.yat-todo[data-waiting=true]::after,.yat-todo[data-frozen=true]::after,.yat-todo[data-running=true]::after{content:"";position:absolute;z-index:2;top:0;bottom:0;left:0;width:3px;background:var(--yat-edge);pointer-events:none}
/* At the ends of the list the bar turns with the list's own curve. The 1px
   is the list's border, which the row sits inside of. */
.yat-todo:first-child::after{border-top-left-radius:calc(var(--sk-radius-lg) - 1px)}
.yat-todo:last-child::after{border-bottom-left-radius:calc(var(--sk-radius-lg) - 1px)}
/* Mid-drag the row is a floating card with all four corners rounded, so the
   bar follows the card instead of whatever place in the list it left. */
.yat-todo[data-dragging=true]::after{border-radius:var(--sk-radius-md) 0 0 var(--sk-radius-md)}
.yat-todo[data-running=true] .yat-todo__body>p{font-weight:650}
/* The body ignores the pointer so a drag can start anywhere on the row; a
   title that opens a checklist has to take it back. */
.yat-todo__title--checklist{pointer-events:auto;cursor:pointer}
.yat-todo__title--checklist:hover{text-decoration:underline}
/* A row that has a checklist is not completed by pressing anywhere on it.
   The steps are the work, and the title, the meta line and the "0/2"
   counter each mean something of their own that the full-row completion
   overlay was swallowing — on a phone the counter marked the task done
   instead of opening the checklist. The overlay stays where it is, since
   it is what places the round box against the row, but stops taking the
   pointer; the box takes it, with a hit area wider than its 1.4rem so a
   finger still finds it. A row without a checklist keeps the whole row as
   its target, which is the large tap target a phone wants. */
.yat-todo[data-checklist=true] .yat-toggle,.yat-todo[data-checklist=true] .yat-check{pointer-events:none}
.yat-todo[data-checklist=true] .yat-check__box{pointer-events:auto}
.yat-todo[data-checklist=true] .yat-check__box::after{content:"";position:absolute;inset:-.65rem;border-radius:50%}
.yat-todo:last-child{border-bottom:0}
.yat-toggle{position:absolute;z-index:1;inset:0;display:grid}.yat-check{position:relative;display:grid;width:100%;height:100%;align-items:center;justify-items:start;border:0;background:transparent;cursor:pointer}.yat-check__box{position:absolute;top:50%;left:1.45rem;display:grid;box-sizing:border-box;width:1.4rem;height:1.4rem;place-items:center;border:1.5px solid var(--sk-color-text-muted);border-radius:.42rem;background:var(--sk-color-surface);transform:translateY(-50%);transition:background 120ms,border-color 120ms,transform 120ms}.yat-check__box:hover{border-color:var(--sk-color-text);background:var(--sk-color-active);transform:translateY(-50%) scale(1.04)}.yat-check[data-checked=true] .yat-check__box{border-color:var(--sk-color-accent);background:var(--sk-color-accent)}.yat-check[data-checked=true] .yat-check__box:hover{background:color-mix(in srgb,var(--sk-color-accent) 82%,var(--sk-color-surface))}.yat-check:focus-visible{outline:0}.yat-check:focus-visible .yat-check__box{outline:2px solid var(--sk-color-focus);outline-offset:2px}.yat-check[data-yat-toggling=true] .yat-check__box{animation:yat-check-toggle 180ms cubic-bezier(.2,.8,.3,1)}.yat-check__box .sk-icon{width:1rem;height:1rem;margin:0;color:var(--sk-color-on-accent)}@keyframes yat-check-toggle{0%,100%{transform:translateY(-50%) scale(1)}45%{transform:translateY(-50%) scale(.78)}75%{transform:translateY(-50%) scale(1.08)}}@media(prefers-reduced-motion:reduce){.yat-check__box{transition:none}.yat-check[data-yat-toggling=true] .yat-check__box{animation:none}}
.yat-todo__body{position:relative;z-index:1;grid-column:2;min-width:0;padding:.35rem;pointer-events:none}.yat-todo__body>p{overflow:hidden;margin:0;font-weight:500;text-overflow:ellipsis;white-space:nowrap}.yat-todo[data-completed=true] .yat-todo__body>p{text-decoration:line-through;color:var(--sk-color-text-muted)}
/* The hour, which is drawn twice over because the space to draw it in is not
   the same space at both widths.

   Narrow, the list runs edge to edge on purpose and has no margin to hang
   anything in, so the hour is a caption over the title — the row buys the line
   it needs with a little more padding at the top.

   Wide, it floats clear of the list altogether, on the page's own background:
   a column of hours beside the card rather than a column inside it. The room
   for it is taken at the page, not at the list, so the heading, filters, rows
   and composer all move over together — indenting the list alone bought the
   strip at the price of their alignment, and cancelling the inset for the
   composer alone bought it at the price of the composer's: its field sat a
   whole strip to the left of every row beneath it.

   What the composer does cancel is only what a sticky bar has to. It reaches
   back out to the page's edge so its background covers the strip, and puts the
   same distance back as padding so the field itself stays on the list's left
   edge — the pattern the untimed bar already follows against the plain gutter.
   Without the reach the hours, which hang outside the list in that strip,
   would scroll up past the bar in the open.

   Taken from the page rather than left to overflow it, too: below about
   1472px the page fills the space beside the sidebar exactly, so an hour
   hanging past its padding would be drawn over the sidebar.

   Either way nothing is paid by a page that names no hours at all. */
.yat-todo-region:has(.yat-todo[data-scheduled-time]){--yat-time-caption:.8rem}
.yat-todo__time{position:absolute;z-index:2;top:.4rem;left:3.8rem;color:var(--sk-color-text-muted);font-size:.66rem;font-weight:650;font-variant-numeric:tabular-nums;letter-spacing:.04em;pointer-events:none}
@media(min-width:48rem){.yat-todo-region:has(.yat-todo[data-scheduled-time]){--yat-time-caption:0rem}.sk-page:has(.yat-todo[data-scheduled-time]){padding-left:calc(var(--sk-gutter) + 3.6rem)}.sk-page:has(.yat-todo[data-scheduled-time])>.yat-composer{margin-left:calc(var(--sk-gutter)*-1 - 3.6rem);padding-left:calc(var(--sk-gutter) + 3.6rem)}.yat-todo__time{top:50%;left:auto;right:calc(100% + .7rem);width:2.7rem;transform:translateY(-50%);font-size:.78rem;font-weight:600;letter-spacing:-.01em;text-align:right}}
/* Clipped, not hidden. The row has to keep a long meta line from spilling,
   but overflow:hidden cut the top and bottom off the focus ring on the
   indicators in here — a pill outline with its horizontals sliced away, which
   read as a pair of black parentheses around the icon. `clip` with a margin
   clips the content and lets the ring paint past it.
   Only sideways, though: a long line only ever spills to the right, and
   clipping upwards as well cut the tooltips on these indicators down to the
   bottom edge of their bubble — a pale smear across the title on hover. */
.yat-todo__meta{display:flex;align-items:center;gap:.4rem;min-width:0;margin-top:.25rem;color:var(--sk-color-text-muted);font-size:.76rem;white-space:nowrap;overflow-x:clip;overflow-y:visible;overflow-clip-margin:.45rem}.yat-todo__meta>*+*::before{content:"·";margin-right:.4rem}.yat-waiting-tag,.yat-frozen-tag{display:inline-flex;align-items:center;padding:.08rem .38rem;border:1px solid color-mix(in srgb,var(--sk-color-text-muted) 45%,transparent);border-radius:999px;font-size:.62rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase}.yat-todo__meta>.yat-waiting-tag+*::before,.yat-todo__meta>.yat-frozen-tag+*::before{display:none}.yat-todo__author{display:inline-flex;align-items:center}.yat-todo__author::before{display:none}.yat-todo__avatar{display:inline-grid;width:1.35rem;height:1.35rem;place-items:center;border-radius:50%;background:var(--sk-color-active);color:var(--sk-color-text-muted);font-size:.58rem;font-weight:700}.yat-note-indicator{display:inline-flex;align-items:center;padding:0;border:0;background:transparent;color:inherit;cursor:pointer;pointer-events:auto}.yat-recurring-indicator{display:inline-flex;align-items:center;color:inherit}
.yat-todo-link{position:relative;z-index:2;display:inline-flex;align-items:center;padding:.1rem;border-radius:var(--sk-radius-sm);color:inherit;cursor:pointer;pointer-events:auto}.yat-todo-link:hover{background:var(--sk-color-active);color:var(--sk-color-text)}.yat-todo-link:focus-visible{outline:2px solid var(--sk-color-focus);outline-offset:2px}.yat-todo-link .sk-icon{width:.9rem;height:.9rem}
/* "Completed a week ago" sits beside "3d ago" in the same line, and one of
   them was a button with the browser's own chrome around it. It still opens
   the date dialog; it simply reads as the sentence it is. */
.yat-completed-date{padding:0;border:0;background:transparent;color:inherit;font:inherit;cursor:pointer;pointer-events:auto}
.yat-completed-date:hover,.yat-completed-date:focus-visible{text-decoration:underline}.yat-note-indicator .sk-icon{width:.9rem;height:.9rem}
/* Hidden by default on a phone; the long-press controller opts one row in. The
   hover-reveal is the desktop behaviour, declared at 48rem. */
.yat-todo__actions{position:relative;z-index:2;grid-column:2;display:none;flex-wrap:wrap;align-items:center;justify-content:flex-end}
.yat-todo[data-actions-open=true] .yat-todo__actions{display:flex}
/* The handle that says a row can be moved, which nothing used to say: the
   affordance lived behind a mode you had to already want. Modelled on the
   checklist grip, which is this file's own answer to the same question — a
   press that could mean four things must not also mean "pick this up".

   Hidden on a phone. There the row already carries a swipe, and the gesture
   that reorders is the long press, which costs the row nothing to advertise. */
.yat-drag-handle{position:absolute;top:50%;left:calc(100% + .7rem);transform:translateY(-50%);z-index:2;display:none;place-items:center;padding:.25rem;border:0;border-radius:var(--sk-radius-sm);background:transparent;color:var(--sk-color-text-muted);opacity:0;cursor:grab;touch-action:none;transition:opacity 120ms}
.yat-todo .yat-drag-handle{position:absolute}
/* Reserve the outside handle strip even when the page fills the viewport. */
@media(min-width:48rem){.sk-page--action-bar{padding-right:calc(var(--sk-gutter) + 2rem)}}
.yat-drag-handle:active{cursor:grabbing}
.yat-drag-handle:focus-visible{outline:2px solid var(--sk-color-focus);outline-offset:2px}
@media(min-width:48rem){.yat-drag-handle{display:grid}.yat-todo:hover .yat-drag-handle,.yat-todo:focus-within .yat-drag-handle,.yat-todo[data-dragging=true] .yat-drag-handle{opacity:.6}.yat-todo .yat-drag-handle:hover{opacity:1}}
@media(min-width:48rem){.yat-todo__actions{display:flex;grid-column:3;flex-wrap:nowrap;justify-content:flex-start;opacity:0;pointer-events:none;transition:opacity 120ms}.yat-todo:hover .yat-todo__actions,.yat-todo:focus-within .yat-todo__actions{opacity:1;pointer-events:auto}}
.yat-todo-menu{position:relative}.yat-todo-menu>summary{list-style:none}.yat-todo-menu>summary::-webkit-details-marker{display:none}
/* A 12rem dropdown pinned to the right edge of a narrow row lands half off
   screen, so on a phone the overflow menu is a bottom sheet instead. */
.yat-todo-menu__panel{position:fixed;z-index:30;inset:auto 0 0;display:grid;width:100%;padding:.35rem .35rem calc(.35rem + var(--sk-safe-bottom));border:1px solid var(--sk-color-border);border-radius:var(--sk-radius-xl) var(--sk-radius-xl) 0 0;background:var(--sk-color-surface);box-shadow:var(--sk-component-shadow-panel)}
@media(min-width:48rem){.yat-todo-menu__panel{position:absolute;inset:auto 0 auto auto;width:min(12rem,calc(100vw - 3rem));padding:.35rem;border-radius:var(--sk-radius-lg)}}
.yat-todo-menu__item{display:flex;width:100%;min-height:var(--sk-size-touch);align-items:center;gap:.6rem;padding:0 .6rem;border:0;border-radius:var(--sk-radius-md);background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer}.yat-todo-menu__item:hover{background:var(--sk-color-active)}form.yat-todo-menu__item{padding:0;display:block}form.yat-todo-menu__item>button{display:flex;width:100%;min-height:var(--sk-size-touch);align-items:center;gap:.6rem;padding:0 .6rem;border:0;border-radius:var(--sk-radius-md);background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer}form.yat-todo-menu__item[data-yat-delete]>button{color:var(--sk-color-danger)}form.yat-todo-menu__item>button:hover{background:var(--sk-color-active)}
.yat-todo-schedule>.yat-todo-menu__panel>form{display:grid}
/* A tooltip sits over the control it describes. It used to be pinned with
   right:0, so a bubble wider than its control — 'Start date' over a
   2.75rem square — grew leftwards and ended up beside the control,
   reading as though it belonged to whatever was next to it.

   Centring alone would trade that for bubbles running off the window,
   which is why right-alignment was chosen in the first place: most of
   these controls are row actions at the right edge. So placement is three
   inherited variables and an edge is declared once, on the container that
   is at one — which is also what stops the two tooltip mechanisms in this
   file from drifting apart: [data-yat-tooltip]::after and .yat-tooltip
   read the same three. Default is centred. */
.yat-todo__actions,.sk-page-heading__aside,.yat-tracker__actions,.yat-time-entry__actions,.yat-todo-menu{--yat-tooltip-left:auto;--yat-tooltip-right:0;--yat-tooltip-x:0}
.sk-sidebar{--yat-tooltip-left:0;--yat-tooltip-right:auto;--yat-tooltip-x:0}
@media(min-width:48rem) and (hover:hover) and (pointer:fine){[data-yat-tooltip]{position:relative}[data-yat-tooltip]::after{content:attr(data-yat-tooltip);position:absolute;z-index:40;left:var(--yat-tooltip-left,50%);right:var(--yat-tooltip-right,auto);bottom:calc(100% + .45rem);width:max-content;max-width:14rem;padding:.35rem .5rem;border:1px solid var(--sk-color-border);border-radius:var(--sk-radius-sm);background:var(--sk-color-surface);box-shadow:var(--sk-component-shadow-panel);color:var(--sk-color-text);font-size:.72rem;font-weight:500;line-height:1.2;white-space:nowrap;opacity:0;pointer-events:none;transform:translate(var(--yat-tooltip-x,-50%),.2rem);transition:opacity 120ms,transform 120ms}[data-yat-tooltip]:hover::after,[data-yat-tooltip]:focus-visible::after{opacity:1;transform:translate(var(--yat-tooltip-x,-50%),0)}
}
/* Row dialogs are fetched into #yat-row-dialogs, outside the row they belong
   to, so they are reached through the fragment's own wrapper. */
.yat-row-dialogs .sk-modal form{display:grid;gap:.75rem}.yat-row-dialogs .sk-modal .sk-button{justify-self:start}
/* Custom scheduling is a small decision over the list, not a context switch:
   keep the page visible behind its modal while the native calendar is open. */
.yat-schedule-date-modal::backdrop{background:transparent;backdrop-filter:none}
/* The tags on the edit sheet. Each is the chip it will be on the row, so
   checking one is a preview of the result rather than a promise about it; an
   unchecked one is the same chip drained to its outline. */
.yat-todo-labels{padding:0;border:0;margin:0}
.yat-todo-labels>legend{padding:0;margin-bottom:.4rem;color:var(--sk-color-text-muted);font-size:.85rem}
.yat-todo-labels__options{display:flex;flex-wrap:wrap;gap:.35rem}
.yat-todo-labels__empty{margin:0;color:var(--sk-color-text-muted);font-size:.85rem}
/* A label looks like a label wherever it is. This is the same object as the
   .yat-label-chip on a task row — filled in its own colour — and only its size
   differs, because here it is something to press. It used to be an outline that
   filled in when chosen, so the same label was two different things depending
   on which panel you were looking at. Chosen is a ring around it instead: the
   fill is what the label is, not whether it is picked. */
.yat-todo-label-toggle{position:relative;display:inline-flex;min-height:2.25rem;align-items:center;padding:0 .7rem;border:1px solid transparent;border-radius:999px;background:var(--yat-label);color:var(--yat-label-ink,#fff);font-size:.85rem;font-weight:600;cursor:pointer}
.yat-todo-label-toggle input{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:pointer}
/* The gap is drawn in the surface colour so the ring reads as a ring against
   any of the seven label colours. */
.yat-todo-label-toggle:has(input:checked){box-shadow:0 0 0 2px var(--sk-color-surface),0 0 0 4px var(--sk-color-text)}
.yat-todo-label-toggle:has(input:focus-visible){outline:2px solid var(--sk-color-focus);outline-offset:2px}
/* Clear of the ring, so a chosen label being focused shows both. */
.yat-todo-label-toggle:has(input:checked):has(input:focus-visible){outline-offset:6px}
/* A box-shadow is dropped in forced colours, which would leave chosen and
   unchosen identical. An outline is not, and costs no layout. */
@media(forced-colors:active){.yat-todo-label-toggle:has(input:checked){outline:3px solid CanvasText;outline-offset:2px}}
.yat-checklist-indicator{display:inline-flex;align-items:center;gap:.25rem;padding:0;border:0;background:transparent;color:inherit;font-size:.76rem;cursor:pointer;pointer-events:auto}.yat-checklist-indicator .sk-icon{width:.9rem;height:.9rem}
.yat-checklist-panel{display:grid;gap:.85rem}.yat-checklist-progress{margin:0;color:var(--sk-color-text-muted);font-size:.85rem}
/* No scroll box of its own: the modal body already scrolls, and a box inside
   it put a second pair of scrollbars in a dialog with six short items. */
.yat-checklist-list{display:grid;gap:.15rem;padding:0;margin:0;list-style:none}
.yat-checklist-item{display:flex;align-items:center;gap:.5rem;padding:.25rem 0;background:var(--sk-color-surface)}
/* The grip, and only the grip. The row already carries a checkbox, a title and
   a delete; a press that could mean any of those must not also mean "pick this
   up". It fades in on hover so a still list stays a list of steps. */
.yat-checklist-grip{display:grid;flex:none;place-items:center;color:var(--sk-color-text-muted);opacity:0;cursor:grab;touch-action:none;transition:opacity 120ms}
.yat-checklist-item:hover .yat-checklist-grip,.yat-checklist-item:focus-within .yat-checklist-grip,.yat-checklist-item[data-dragging=true] .yat-checklist-grip{opacity:.6}
.yat-checklist-item[data-dragging=true]{position:relative;z-index:2;border-radius:var(--sk-radius-sm);box-shadow:var(--sk-component-shadow-panel);cursor:grabbing}
@media(hover:none){.yat-checklist-grip{opacity:.5}}
/* The generic icon button is a 2.75rem square with a grey hover fill, which
   inside a list this tight reads as a box appearing under the pointer. The
   delete keeps the touch target and loses the fill, saying what it does in
   colour instead. */
/* Its tooltip hangs left from the right edge: centred on the last column, the
   hidden label stuck out past the list and gave it a horizontal scrollbar. */
.yat-checklist-delete{--yat-tooltip-left:auto;--yat-tooltip-right:0;--yat-tooltip-x:0}
.yat-checklist-delete .sk-icon-button{width:2rem;height:2rem;min-width:0;min-height:0;color:var(--sk-color-text-muted)}
.yat-checklist-delete .sk-icon-button:hover{background:transparent;color:var(--sk-color-danger)}
.yat-checklist-delete .sk-icon-button:focus-visible{background:transparent;color:var(--sk-color-danger)}
.yat-checklist-check{display:grid;flex:none;width:1.4rem;height:1.4rem;padding:0;place-items:center;border:1.5px solid var(--sk-color-text-muted);border-radius:.4rem;background:var(--sk-color-surface);color:var(--sk-color-on-accent);cursor:pointer}.yat-checklist-check[data-checked=true]{border-color:var(--sk-color-accent);background:var(--sk-color-accent)}.yat-checklist-check .sk-icon{width:1rem;height:1rem;color:var(--sk-color-on-accent)}
.yat-checklist-item__title{flex:1;min-width:0;overflow-wrap:anywhere;font-size:.9rem}.yat-checklist-item__title[data-done=true]{color:var(--sk-color-text-muted);text-decoration:line-through}
/* Outranks the dialog's grid; the pair itself is .yat-pair. */
.yat-row-dialogs .sk-modal form.yat-pair{display:flex}
/* `display:flex` would otherwise outrank the [hidden] the filter sets. */
.yat-completed-actions[hidden]{display:none}
.yat-completed-actions{display:flex;flex-wrap:wrap;align-items:center;gap:1rem;justify-self:start;padding-left:1.45rem;color:var(--sk-color-text-muted);font-size:.8rem}.yat-completed-actions form{margin:0}.yat-completed-actions form>button,.yat-clear-completed>button{padding:.25rem 0;border:0;background:transparent;color:inherit;cursor:pointer}.yat-completed-actions form>button:hover,.yat-clear-completed>button:hover{text-decoration:underline;color:var(--sk-color-text)}.yat-modal-actions{display:flex;justify-content:flex-end;gap:.75rem}
.yat-waiting,.yat-frozen,.yat-scheduled,.yat-archive{display:grid;gap:.6rem;margin-top:1.25rem}.yat-waiting>summary,.yat-frozen>summary,.yat-scheduled>summary,.yat-archive>summary{display:flex;align-items:center;gap:.45rem;width:max-content;padding:.35rem;color:var(--sk-color-text-muted);font-size:.85rem;font-weight:650;cursor:pointer;list-style:none}.yat-waiting>summary small,.yat-frozen>summary small,.yat-scheduled>summary small,.yat-archive>summary small{font-size:.72rem;font-weight:400}.yat-waiting>summary small::before,.yat-frozen>summary small::before,.yat-scheduled>summary small::before,.yat-archive>summary small::before{content:"·";margin-right:.45rem}.yat-waiting>.yat-todo-list,.yat-frozen>.yat-todo-list,.yat-scheduled>.yat-todo-list,.yat-archive>.yat-todo-list{border-style:dashed}
/* A label is filled in its own colour, which is the only thing on the row that
   carries the visitor's own meaning. `--yat-label-ink` is chosen per label by
   the server from the fill's luminance rather than from the theme: the chip
   looks the same in light and dark, so its text cannot follow the page.

   The pair arrives as a class rather than a `style` attribute, because YAT
   sends `style-src 'self'` and that directive governs style attributes too
   when no `style-src-attr` is set — every inline colour was being discarded
   by the browser and labels rendered colourless. The seven classes below are
   the seven colours the palette offers; the ink values are what
   `views/label-ink` computes for each fill, which a test keeps honest. */
/* One ink for the whole set. Every colour here clears 4.5:1 against #181818,
   which is what stops a row of labels reading as two families — the old
   mid-tones took white text on five of the seven and dark on the other two. */
.yat-label--0{--yat-label:#cbd5e1;--yat-label-ink:#181818}
.yat-label--1{--yat-label:#93c5fd;--yat-label-ink:#181818}
.yat-label--2{--yat-label:#86efac;--yat-label-ink:#181818}
.yat-label--3{--yat-label:#fcd34d;--yat-label-ink:#181818}
.yat-label--4{--yat-label:#fca5a5;--yat-label-ink:#181818}
.yat-label--5{--yat-label:#c4b5fd;--yat-label-ink:#181818}
.yat-label--6{--yat-label:#f9a8d4;--yat-label-ink:#181818}
.yat-label-chip{padding:.08rem .45rem;border:1px solid transparent;border-radius:999px;background:var(--yat-label);color:var(--yat-label-ink,#fff);font:inherit;font-weight:600;cursor:pointer;pointer-events:auto}
.yat-label-chip:hover{border-color:color-mix(in srgb,var(--yat-label-ink,#fff) 55%,transparent)}
/* Chips carry their own edges, so the meta row's interpunct between two of
   them is one separator too many. */
.yat-todo__meta>.yat-label-chip+.yat-label-chip::before{display:none}
.yat-todo__meta>.yat-label-chip{margin-right:.05rem}.yat-scheduled-tag{font-weight:650}
/* The running clock says what it is by ticking and by its fill. Weight on top of
   that shouts, so it stays at the meta line's own weight. */
.yat-running{font-weight:inherit}/* An overdue start reads as a warning rather than as a date that quietly
   passed. The words say it too — "Started 3 days ago" — so the colour is a
   reinforcement. */
.yat-scheduled-tag[data-overdue=true]{color:var(--sk-color-danger)}
.yat-running{display:inline-flex;align-items:center;gap:.3rem;padding:.08rem .45rem;border:0;border-radius:999px;background:var(--sk-color-success);color:var(--sk-color-on-accent);font:inherit;font-size:inherit;font-variant-numeric:tabular-nums;cursor:pointer;pointer-events:auto}
/* It stops the clock, so it has to read as a control rather than as a
   status chip — otherwise nobody presses it, and the one who does presses
   it by accident. */
.yat-running-form{display:inline-flex;pointer-events:auto}
.yat-running:hover{background:color-mix(in srgb,var(--sk-color-success) 82%,var(--sk-color-text))}
.yat-running::before{content:"";width:.4rem;height:.4rem;border-radius:50%;background:currentColor}
.yat-todo__meta>.yat-running+*::before{display:none}
/* The start date, collapsed. The toggle is the width of its icon until a date
   is chosen, then it grows by the few characters that date needs — "Today",
   "Tomorrow", or "12 Aug" — so the field keeps the row it had. The panel opens
   upward, because on a phone the composer is pinned to the bottom edge. */
.yat-date-control{position:relative;display:flex;flex:none}
.yat-date-control__toggle{display:inline-flex;min-height:var(--sk-size-touch);align-items:center;gap:.35rem;padding:0 .6rem;border:1px solid var(--sk-color-border);border-radius:var(--sk-radius-md);background:var(--sk-color-surface);color:var(--sk-color-text-muted);font:inherit;cursor:pointer}
.yat-date-control__toggle:hover{color:var(--sk-color-text)}
.yat-date-control[data-set=true] .yat-date-control__toggle{border-color:var(--sk-color-accent);color:var(--sk-color-text)}
.yat-date-control__value{font-size:.78rem;font-weight:650;white-space:nowrap}
.yat-date-control__value[hidden]{display:none}
.yat-date-control__panel{position:absolute;z-index:50;inset:auto auto calc(100% + .45rem) 0;display:grid;width:max-content;max-width:min(18rem,calc(100vw - 2rem));gap:.55rem;padding:.65rem;border:1px solid var(--sk-color-border);border-radius:var(--sk-radius-md);background:var(--sk-color-surface);box-shadow:var(--sk-component-shadow-panel)}
@media(min-width:48rem){.yat-date-control__panel{inset:auto 0 calc(100% + .45rem) auto}}
.yat-date-control__panel[hidden]{display:none}
.yat-date-control__presets{display:flex;flex-wrap:wrap;gap:.35rem}
.yat-date-control__presets button,.yat-date-control__clear{min-height:2.25rem;padding:0 .7rem;border:1px solid var(--sk-color-border);border-radius:999px;background:var(--sk-color-surface);color:inherit;font:inherit;font-size:.8rem;cursor:pointer}
.yat-date-control__presets button:hover,.yat-date-control__clear:hover{background:var(--sk-color-active)}
.yat-date-control__panel input{min-height:var(--sk-size-control);padding:0 .6rem;border:1px solid var(--sk-color-border);border-radius:var(--sk-radius-md);background:var(--sk-color-surface);color:inherit;font:inherit}
.yat-date-control__clear{justify-self:start;border-color:transparent;color:var(--sk-color-text-muted)}
/* The typed form of the same thing, spelled out where somebody who wants a
   date is already looking. */
.yat-date-control__syntax{color:var(--sk-color-text-muted);font-size:.72rem;line-height:1.3}
.yat-date-control__syntax code{padding:0 .15rem;border-radius:var(--sk-radius-sm);background:var(--sk-color-active);font-family:var(--sk-font-mono,ui-monospace,monospace)}
/* The anchor the suggestions hang from, and the rule that quietly unpinned the
   composer for a year: this file is loaded after the UI package, so a bare
   .yat-composer beats .sk-action-bar's `position:fixed` on source order alone
   and the bar scrolled away with the list. The phone is positioned by the
   sticky rule at the top of this file, which is specific enough to win here;
   this one is the wide layout's anchor, where the bar is static anyway. */
.yat-composer{position:relative}
.yat-smart-suggestions{position:absolute;z-index:50;inset:auto 3.5rem calc(100% + .35rem) 0;max-height:14rem;padding:.35rem;border:1px solid var(--sk-color-border);border-radius:var(--sk-radius-md);background:var(--sk-color-surface);box-shadow:var(--sk-component-shadow-panel);overflow:auto}.yat-smart-suggestions button{display:block;width:100%;padding:.55rem;border:0;border-radius:var(--sk-radius-sm);background:transparent;color:inherit;text-align:left}.yat-smart-suggestions button:hover{background:var(--sk-color-active)}
.yat-member-avatar,.yat-member-avatar{width:2.25rem;height:2.25rem}.yat-pending-invitations ul,/* A rule reads as its title and when it next fires, with the three things that
   can be done to it at the end of the row. */
.yat-recurrence-list{display:grid;gap:.5rem;padding:0;margin:0;list-style:none}
.yat-recurrence-rule__title{display:grid;min-width:0;flex:1;gap:.1rem}
.yat-recurrence-rule__title>span{color:var(--sk-color-text-muted);font-size:.78rem}
.yat-recurrence-rule__actions{display:flex;flex:none;align-items:center;gap:.15rem}
.yat-recurrence-rules>p{margin:0;color:var(--sk-color-text-muted);font-size:.85rem}
/* A destructive action spanning a whole card reads as the card's purpose. It
   sits at the end of its own sentence instead. */
.yat-settings-action{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:1rem}
.yat-settings-action>p{flex:1 1 14rem;min-width:0;margin:0}
.yat-settings-action>form{display:block;flex:none}.yat-pending-invitations li,.yat-recurrence-list li{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem}.yat-pending-invitations li>div:first-child,
/* The label manager. A row is name, colour, save, delete — and it wraps rather
   than shrinking, because the swatches are a fixed size: they are touch targets
   and a colour too small to read is not a choice. */
/* minmax(0,1fr), not the default auto track. An auto track is at least the
   min-content of what is in it, and a label row's min-content is its name
   field plus seven 2rem swatches plus two buttons — around 32rem, which on
   a phone made the grid wider than the dialog holding it and pushed the
   whole viewport sideways. The row is built to give way (the name shrinks
   first, then the swatches scroll), and could not, because the track it sat
   in refused to. Both grids here need it: the manager and its list. */
.yat-label-manager{display:grid;grid-template-columns:minmax(0,1fr);gap:.4rem}
/* Same shape as Add member: a summary that reads as a button, and the form
   underneath once it is asked for. */
.yat-new-label>summary{width:max-content;list-style:none}
.yat-new-label>summary::-webkit-details-marker{display:none}
.yat-new-label>form{margin-top:.75rem}
.yat-label-manager__list{display:grid;grid-template-columns:minmax(0,1fr);gap:.2rem;padding:0;margin:.5rem 0 0;list-style:none}
.yat-label-manager__list li{display:flex;align-items:center;gap:.25rem}
/* One label, one line. The row used to wrap: seven swatches at touch size plus
   a name field would not fit a modal's width, so the colours dropped to a
   second line and took the save tick with them, leaving the delete floating
   beside a two-line block. Nothing wraps now — the name gives up width first,
   and the swatches scroll sideways if even that is not enough. */
.yat-label-row{display:flex;flex:1;min-width:0;flex-wrap:nowrap}
.yat-label-row>input:not([type=hidden]){flex:1 1 4rem}
.yat-label-row__save,.yat-label-row__delete{flex:none;width:var(--sk-size-control);height:var(--sk-size-control);min-width:0;min-height:0}
.yat-label-row__delete{color:var(--sk-color-danger)}
/* Radios, so the group is a group for the keyboard without a line of script:
   arrow keys move between the colours and one value is posted. The input is
   the whole swatch and invisible; the span is what is seen. */
.yat-color-swatches{display:flex;flex:0 1 auto;flex-wrap:nowrap;gap:.1rem;padding:0;border:0;margin:0;min-width:0;overflow-x:auto;scrollbar-width:none}
.yat-color-swatch{position:relative;display:grid;width:2rem;min-width:2rem;height:var(--sk-size-touch);place-items:center;cursor:pointer}
.yat-color-swatch input{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:pointer}
.yat-color-swatch>span{width:1.15rem;height:1.15rem;border-radius:50%;background:var(--yat-label);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--sk-color-text) 22%,transparent);transition:width 90ms,height 90ms}
.yat-color-swatch:hover>span{width:1.35rem;height:1.35rem}
/* Chosen is a ring rather than a size, so the selection survives a hover
   landing on a neighbour. */
.yat-color-swatch:has(input:checked)>span{width:1.35rem;height:1.35rem;box-shadow:0 0 0 2px var(--sk-color-surface),0 0 0 4px var(--sk-color-text)}
.yat-color-swatch:has(input:focus-visible)>span{outline:2px solid var(--sk-color-focus);outline-offset:4px}
@media(forced-colors:active){.yat-color-swatch>span{forced-color-adjust:none;border:1px solid CanvasText}.yat-color-swatch:has(input:checked)>span{border:3px solid CanvasText}}
/* Reordering the sidebar, which is a mode. Off, a row is a link and nothing
   about it suggests otherwise; on, every row shows its grip and none of them
   navigate, so the one gesture available is the one the mode is for. */
.sk-sidebar .sk-workspaces .sk-nav-item[data-workspace-id]{position:relative}
.sk-sidebar [data-sk-workspace-reorder=true] .sk-nav-item[data-workspace-id]{cursor:grab;touch-action:none;-webkit-user-select:none;user-select:none}
.sk-sidebar .sk-workspaces .sk-nav-item[data-workspace-id]::after{content:"";position:absolute;top:50%;right:.3rem;width:1rem;height:1rem;background-color:currentColor;opacity:0;transform:translateY(-50%);transition:opacity 120ms;-webkit-mask:url("/skobka/ui/icons/lucide/grip-vertical.svg") center/contain no-repeat;mask:url("/skobka/ui/icons/lucide/grip-vertical.svg") center/contain no-repeat}
.sk-sidebar [data-sk-workspace-reorder=true] .sk-nav-item[data-workspace-id]::after{opacity:.55}
/* The grip is drawn over the row, so the row has to make room for it while the
   mode is armed — a shared workspace's SHARED badge sits exactly where it
   lands, and the two were printed on top of each other. */
.sk-sidebar [data-sk-workspace-reorder=true] .sk-nav-item[data-workspace-id]{padding-right:1.6rem}
.sk-sidebar [data-sk-workspace-reorder-toggle][aria-pressed=true]{background:var(--sk-color-accent);color:var(--sk-color-on-accent)}
/* `will-change:transform` for the same reason the dragging todo row has it: a
   row moved by rewriting its transform repaints in full under Gecko's more
   conservative promotion heuristics, and this row carries a box-shadow and an
   ::after grip painted from a masked SVG — felt as the row lagging behind the
   pointer. The hint puts it on its own layer for the length of the drag. */
.sk-sidebar .sk-nav-item[data-dragging=true]{z-index:5;border-radius:var(--sk-radius-md);background:var(--sk-color-surface);box-shadow:var(--sk-component-shadow-panel);cursor:grabbing;will-change:transform}
html[data-yat-workspace-drag=true]{cursor:grabbing;-webkit-user-select:none;user-select:none}
/* Active work belongs to the page, not to whichever sidebar happens to be
   open. The stack is fixed to the main canvas and stays above the composer. */
.yat-trackers{position:fixed;z-index:100;top:calc(var(--sk-safe-top) + 1rem);left:calc(var(--sk-component-sidebar-width) + 1rem);display:grid;width:min(21rem,calc(100vw - var(--sk-component-sidebar-width) - 2rem));max-height:calc(100dvh - var(--sk-safe-top) - 2rem);gap:.7rem;overflow:auto;overscroll-behavior:contain;scrollbar-width:thin}
.yat-trackers[hidden]{display:none}
.yat-tracker{position:relative;display:grid;gap:.7rem;padding:.85rem;border:1px solid color-mix(in srgb,var(--sk-color-success) 42%,var(--sk-color-border));border-radius:var(--sk-radius-xl);background:linear-gradient(145deg,color-mix(in srgb,var(--sk-color-success) 9%,var(--sk-color-surface)),var(--sk-color-surface) 55%);box-shadow:0 12px 36px color-mix(in srgb,var(--sk-color-text) 14%,transparent),0 2px 8px color-mix(in srgb,var(--sk-color-text) 8%,transparent);transition:transform 140ms ease,box-shadow 140ms ease}
.yat-tracker:hover{transform:translateY(-1px);box-shadow:0 16px 42px color-mix(in srgb,var(--sk-color-text) 17%,transparent),0 3px 10px color-mix(in srgb,var(--sk-color-text) 9%,transparent)}
.yat-tracker__sweep{position:absolute;inset:0 0 auto;height:3px;border-radius:var(--sk-radius-xl) var(--sk-radius-xl) 0 0;background:color-mix(in srgb,var(--sk-color-success) 18%,transparent);overflow:hidden}
.yat-tracker__sweep>span{display:block;width:0;height:100%;background:var(--sk-color-success);transition:width 1s linear}
.yat-tracker__head{display:grid;grid-template-columns:minmax(0,1fr) auto auto;align-items:center;gap:.5rem}
.yat-tracker__state{display:flex;align-items:center;color:var(--sk-color-success);font-size:.7rem;font-weight:800;letter-spacing:.08em;text-transform:uppercase}
.yat-tracker__pulse{width:.48rem;height:.48rem;margin-right:.4rem;border-radius:50%;background:var(--sk-color-success);box-shadow:0 0 0 .22rem color-mix(in srgb,var(--sk-color-success) 15%,transparent);animation:yat-pulse 2s ease-in-out infinite}
@keyframes yat-pulse{0%,100%{opacity:1}50%{opacity:.38}}
.yat-tracker__elapsed{font-family:var(--sk-font-mono);font-size:.82rem;font-weight:650;font-variant-numeric:tabular-nums}
.yat-tracker__dismiss{position:relative;z-index:2;width:1.8rem;min-height:1.8rem;height:1.8rem;color:var(--sk-color-text-muted)}
.yat-tracker__body{display:grid;min-width:0;gap:.25rem}
.yat-tracker__context{display:flex;align-items:center;gap:.3rem;color:var(--sk-color-text-muted);font-size:.72rem}
.yat-tracker__link{display:flex;min-width:0;align-items:center;justify-content:space-between;gap:.6rem;color:inherit;text-decoration:none}
.yat-tracker__link::after{position:absolute;z-index:1;inset:0;border-radius:inherit;content:""}
.yat-tracker__link strong{overflow:hidden;font-family:var(--sk-font-display);font-size:1rem;line-height:1.25;text-overflow:ellipsis;white-space:nowrap}
.yat-tracker__link .sk-icon{flex:none;color:var(--sk-color-text-muted);transition:transform 140ms ease}
.yat-tracker:hover .yat-tracker__link .sk-icon{transform:translateX(.18rem)}
.yat-tracker__actions{position:relative;z-index:2;display:flex;align-items:center;gap:.45rem;padding-top:.65rem;border-top:1px solid color-mix(in srgb,var(--sk-color-border) 78%,transparent)}
.yat-tracker__actions form:first-child{flex:1}.yat-tracker__actions form:first-child .sk-button{width:100%}.yat-tracker__actions .sk-button{gap:.35rem}
@media(max-width:47.999rem){.yat-trackers{top:calc(var(--sk-component-mobile-header-height) + var(--sk-safe-top) + .6rem);right:.7rem;left:.7rem;width:auto;max-height:min(44dvh,25rem)}.yat-tracker{padding:.75rem}}
@media(prefers-reduced-motion:reduce){.yat-tracker,.yat-tracker__link .sk-icon{transition:none}.yat-tracker:hover,.yat-tracker:hover .yat-tracker__link .sk-icon{transform:none}.yat-tracker__pulse{animation:none}.yat-tracker__sweep>span{transition:none}}
@keyframes yat-tracker-flash{0%,100%{box-shadow:0 0 0 0 transparent}18%,65%{box-shadow:0 0 0 4px color-mix(in srgb,var(--sk-color-success) 38%,transparent);background:color-mix(in srgb,var(--sk-color-success) 13%,var(--sk-color-surface))}}
.yat-todo[data-yat-flash=true]{animation:yat-tracker-flash 2.1s ease-out}
/* The import preview. It is a page rather than a panel because it is a whole
   file being read back, and a table of rows in a modal is a table nobody can
   see. */
.yat-import-preview{display:grid;gap:1.25rem}
.yat-import-errors{padding:1rem;border:1px solid var(--sk-color-danger);border-radius:var(--sk-radius-md);background:color-mix(in srgb,var(--sk-color-danger) 7%,transparent)}
.yat-import-errors h2{display:flex;align-items:center;gap:.45rem;margin:0 0 .5rem;color:var(--sk-color-danger);font:var(--sk-type-subheading-weight) var(--sk-type-subheading)/var(--sk-type-subheading-leading) var(--sk-font-display)}
.yat-import-errors p{margin:0 0 .6rem;color:var(--sk-color-text-muted);font-size:.9rem}
.yat-import-errors ul{display:grid;gap:.25rem;margin:0;padding-left:1.1rem;font-size:.9rem}
.yat-import-note{margin:0;color:var(--sk-color-text-muted);font-size:.9rem}
.yat-import-table{overflow-x:auto;border:1px solid var(--sk-color-border);border-radius:var(--sk-radius-md)}
.yat-import-table table{width:100%;border-collapse:collapse;font-size:.9rem}
.yat-import-table th,.yat-import-table td{padding:.5rem .75rem;text-align:left;vertical-align:top}
.yat-import-table thead th{position:sticky;top:0;border-bottom:1px solid var(--sk-color-border);background:var(--sk-color-surface-muted);font-size:.75rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase}
.yat-import-table tbody tr+tr td{border-top:1px solid color-mix(in srgb,var(--sk-color-border) 65%,transparent)}
.yat-import-status{display:inline-flex;padding:.05rem .4rem;border-radius:999px;background:var(--sk-color-active);font-size:.72rem;font-weight:700;letter-spacing:.03em;text-transform:uppercase}
.yat-import-status[data-status=completed],.yat-import-status[data-status=archived]{color:var(--sk-color-text-muted)}
.yat-import-actions{display:flex;flex-wrap:wrap;gap:.75rem}
/* The drop zone is the page, so the target is drawn over the page rather than
   somewhere on it: a rectangle a file has to be aimed at is the thing dragging
   was meant to avoid. */
.yat-drop-target{position:fixed;z-index:120;inset:0;display:grid;place-items:center;background:color-mix(in srgb,var(--sk-color-canvas) 82%,transparent);backdrop-filter:blur(2px);pointer-events:none}
.yat-drop-target[hidden]{display:none}
.yat-drop-target__card{display:grid;justify-items:center;gap:.4rem;padding:2rem 2.5rem;border:2px dashed var(--sk-color-accent);border-radius:var(--sk-radius-xl);background:var(--sk-color-surface);text-align:center}
.yat-drop-target__card strong{font-family:var(--sk-font-display);font-size:1.05rem}
.yat-drop-target__card span{color:var(--sk-color-text-muted);font-size:.85rem}
.yat-drop-target .sk-icon{color:var(--sk-color-accent)}
/* The day view. Sections rather than one list, and every day between today and
   the same day next week is drawn even when empty — an empty Thursday is the
   answer to "what is on Thursday". */
.yat-todo-region[data-view-mode=days]{gap:1.5rem}
/* The day groups are children of the region's inner section, not of the region,
   so the gap above never reached them: one day's last task sat flush against
   the next day's heading, with only a 1px list border between them. The space
   goes where the groups actually are, and each group's own gap is tightened so
   a heading reads as belonging to the tasks under it. */
.yat-todo-region[data-view-mode=days]>section{display:grid;gap:1.75rem}
.yat-day{display:grid;gap:.3rem}
/* The heading is the summary now: a day that holds nothing costs one line
   instead of a band of empty screen, and the gap between days closes with it. */
.yat-day>summary{display:flex;align-items:baseline;gap:.5rem;margin:0;font:var(--sk-type-subheading-weight) var(--sk-type-subheading)/var(--sk-type-subheading-leading) var(--sk-font-display);letter-spacing:var(--sk-type-subheading-tracking);list-style:none;cursor:pointer}
.yat-day>summary::-webkit-details-marker{display:none}.yat-day__disclosure{flex:none;align-self:center;color:inherit;transition:transform 150ms}.yat-day[open]>summary .yat-day__disclosure{transform:rotate(180deg)}@media(prefers-reduced-motion:reduce){.yat-day__disclosure{transition:none}}
.yat-day>summary small{color:var(--sk-color-text-muted);font-family:var(--sk-font-body,inherit);font-size:.75rem;font-weight:400}
.yat-day:not([open]){gap:0}
.yat-day__count{margin-left:auto;color:var(--sk-color-text-muted);font-size:.8rem;font-weight:500}
/* Under the day's tasks and against their right edge, where an action on the
   whole day reads as following from what it acted on. It says what it does:
   the arrow it replaces sat in the heading and named nothing. */
.yat-day__foot{display:flex;justify-content:flex-end}
.yat-day__push{padding:.25rem .5rem;border:0;border-radius:var(--sk-radius-sm);background-color:transparent;color:var(--sk-color-text-muted);font:inherit;font-size:.8rem;cursor:pointer}
.yat-day__push:hover{background-color:var(--sk-color-active);color:var(--sk-color-text)}
.yat-day__push[data-pending=true]{opacity:.5;pointer-events:none}
.yat-day[data-day-key=overdue]>summary{color:var(--sk-color-danger)}
/* Today, Tomorrow and each named weekday already date every row beneath their
   heading. Overdue and Later span several dates, so their row markers remain. */
.yat-day[data-day-date] .yat-scheduled-tag{display:none}
html[data-yat-day-drag=true]{cursor:grabbing;-webkit-user-select:none;user-select:none}
html[data-yat-day-drag=true] .yat-todo[data-dragging=true]{z-index:6;border-radius:var(--sk-radius-md);background:var(--sk-color-surface);box-shadow:var(--sk-component-shadow-panel)}
/* Swipe actions: a finger's answer to "when", in place of the ring it cannot
   use. The row itself carries the transform — the same trick the reorder drag
   already relies on — and stays opaque and on top of the floating panel a
   swipe reveals underneath it, positioned at the row's own rect the moment
   the gesture decides which way it is going. */
.yat-todo[data-yat-swiping=true]{z-index:5;background:var(--sk-color-surface);will-change:transform}
.yat-swipe-panel{position:fixed;z-index:4;display:flex;overflow:hidden;border-radius:var(--sk-radius-lg)}
.yat-swipe-panel--start{justify-content:flex-start}
.yat-swipe-panel--end{justify-content:flex-end}
.yat-swipe-panel__action{display:flex;flex-direction:column;flex:none;align-items:center;justify-content:center;gap:.2rem;width:4.5rem;border:0;background:var(--sk-color-text-muted);color:var(--sk-color-surface);font:inherit;font-size:.68rem;font-weight:600}
.yat-swipe-panel--start .yat-swipe-panel__action{background:var(--sk-color-accent);color:var(--sk-color-on-accent)}
/* The ring: the answers, around the point the drag set off from. Drawn
   only while something is in the air and never hit-tested — the answer comes
   out of an angle, not out of what the pointer happens to be over. It sits
   above every YAT page layer, including the pinned composer and drop target,
   so text beneath the gesture cannot paint over its answers. */
.yat-day-ring{display:none;position:fixed;z-index:130;width:19rem;height:19rem;transform:translate(-50%,-50%);border-radius:50%;background:radial-gradient(closest-side,transparent 27%,color-mix(in srgb,var(--sk-color-text) 7%,transparent) 27%);pointer-events:none}
html[data-yat-day-drag=true] .yat-day-ring{display:block}
/* The armed wedge. Script writes where it starts and how wide it is as custom
   properties, because the number of answers is not fixed: a list that keeps
   no frozen items is asked the same question with one wedge fewer. The
   colours stay here; `style-src 'self'` keeps a whole gradient out of the
   markup, and nothing script writes is one.
   The gradient itself is painted once, pointing north — only its width
   varies, and that is set a single time per drag, not per pointer move.
   Which wedge is lit turns with a `rotate`, not by asking the gradient to
   repaint at a new angle: a transform composites, and repainting a masked
   conic-gradient on every pointer move is expensive enough in Gecko to be
   felt as dropped frames while the ring tracks the pointer. */
.yat-day-ring{--yat-ring-wedge:72deg;--yat-ring-from:-36deg}
.yat-day-ring::before{content:"";position:absolute;inset:0;border-radius:50%;-webkit-mask:radial-gradient(closest-side,transparent 27%,#000 27%);mask:radial-gradient(closest-side,transparent 27%,#000 27%)}
.yat-day-ring[data-active]::before{background:conic-gradient(from 0deg,color-mix(in srgb,var(--sk-color-accent) 18%,transparent) 0 var(--yat-ring-wedge),transparent 0);transform:rotate(var(--yat-ring-from));will-change:transform}
/* Each answer sits where its wedge points, which is the same two numbers
   again — placed by script, styled here. The icon is the one the schedule menu
   gives the same answer. */
.yat-day-ring__option{position:absolute;top:var(--yat-ring-y);left:var(--yat-ring-x);display:flex;align-items:center;gap:.3rem;padding:.3rem .65rem;transform:translate(-50%,-50%);border:1px solid var(--sk-color-border);border-radius:999px;background:var(--sk-color-surface);box-shadow:var(--sk-component-shadow-panel);color:var(--sk-color-text-muted);font-size:.78rem;font-weight:600;white-space:nowrap}
.yat-day-ring__option[data-armed=true]{border-color:var(--sk-color-accent);color:var(--sk-color-accent)}
/* The middle is where a drag that has changed its mind ends, so it says so —
   and stops saying it the moment an answer is armed. */
.yat-day-ring__middle{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);color:var(--sk-color-text-muted);font-size:.72rem;font-weight:600}
.yat-day-ring[data-active] .yat-day-ring__middle{opacity:0}
.yat-day[data-day-key=done]>summary,.yat-day[data-day-key=inbox]>summary{color:var(--sk-color-text-muted)}
.yat-manage,.yat-danger-zone{margin-top:2rem}
/* Every card on a YAT page is a panel, so its h2 is the shared panel step. */
.yat-settings h2,.yat-workspace-settings h2{margin:.25rem 0;font:var(--sk-type-heading-weight) var(--sk-type-heading)/var(--sk-type-heading-leading) var(--sk-font-display);letter-spacing:var(--sk-type-heading-tracking)}
.yat-member-list{display:grid;gap:.2rem;padding:0;margin:1rem 0;list-style:none}.yat-member-list li{display:flex;min-height:3.25rem;align-items:center;gap:.75rem;padding:.45rem .25rem}/* The name and the address are two lines, and the address is the quieter of
   them. This used to be addressed as `li>div:first-child`, which is the
   avatar, so the rule never applied and the two ran together into one line.
   An address has no spaces to break on, so it is told it may break anywhere
   rather than being cut off. */
.yat-member-identity{display:grid;flex:1;min-width:0}
.yat-member-identity strong{overflow-wrap:anywhere}
.yat-member-identity small{overflow-wrap:anywhere;line-height:1.35}.yat-member-list strong{font-weight:550}.yat-member-list small{color:var(--sk-color-text-muted)}.yat-member-actions{display:flex}.yat-member-actions form{display:flex}.yat-new-workspace{display:grid;gap:.75rem;padding:.5rem}.yat-add-member>summary{width:max-content;list-style:none}.yat-add-member>form{margin-top:.75rem}
/* The modal body is the scroller — `.sk-modal__body` is already `flex:1;
   overflow-y:auto`. A second `overflow-y` here made the settings a scroll
   region inside a scroll region: the page bar moved nothing while the pointer
   was over the panel, and the panel's own bar was easy to miss entirely. */
.yat-workspace-settings{display:grid;gap:.4rem}
/* Each concern of the settings panel is a <details>, which costs no script and
   keeps the keyboard's own behaviour: a summary is a button. */
.yat-settings-section{border:1px solid var(--sk-color-border);border-radius:var(--sk-radius-md);background:var(--sk-color-surface)}
.yat-settings-section>summary{display:flex;min-height:var(--sk-size-touch);align-items:center;gap:.5rem;padding:.4rem .85rem;font-family:var(--sk-font-display);font-weight:650;cursor:pointer;list-style:none}
.yat-settings-section>summary::-webkit-details-marker{display:none}
.yat-settings-section>summary>span{flex:1;min-width:0}
/* The note gives way rather than pushing. Its default min-width is its own
   text, so a long one — "Deleting this workspace…" — made the summary wider
   than the dialog and the whole panel scrolled sideways to reach it. */
.yat-settings-section>summary small{min-width:0;overflow:hidden;color:var(--sk-color-text-muted);font-family:var(--sk-font-body,inherit);font-size:.75rem;font-weight:400;white-space:nowrap;text-overflow:ellipsis}
.yat-settings-section>summary .sk-icon{flex:none;color:var(--sk-color-text-muted);transition:transform 120ms}
.yat-settings-section[open]>summary .sk-icon{transform:rotate(180deg)}
.yat-settings-section>*:not(summary){padding:0 .85rem .9rem}
.yat-settings-section--danger{border-color:color-mix(in srgb,var(--sk-color-danger) 55%,transparent)}
.yat-settings-section--danger>summary{color:var(--sk-color-danger)}
.yat-settings-section--danger>summary .sk-icon{color:inherit}.yat-workspace-settings h3{margin:0 0 .3rem;font:var(--sk-type-subheading-weight) var(--sk-type-subheading)/var(--sk-type-subheading-leading) var(--sk-font-display);letter-spacing:var(--sk-type-subheading-tracking)}.yat-workspace-settings p{margin:.1rem 0 .5rem;color:var(--sk-color-text-muted);font-size:.9rem}/* This rule predates the split into <details>. Now that it is the only child
   of the first section, its bottom border drew a second line inside a box that
   already has one — a separator under the first open section that separated
   nothing from nothing.

   The gap is the small one: it is the space between two things in the same
   subsection. What sets one subsection apart from the next is the margin above
   its heading, below. */
.yat-owner-settings{display:grid;gap:.45rem}
.yat-owner-settings>h3+*{margin-top:0}
.yat-owner-settings>*+h3{margin-top:1.15rem}.yat-workspace-danger{padding:1rem;border:1px solid color-mix(in srgb,var(--sk-color-danger) 55%,transparent);border-radius:var(--sk-radius-md);background:color-mix(in srgb,var(--sk-color-danger) 6%,transparent)}.yat-workspace-danger h3,.yat-workspace-danger summary{color:var(--sk-color-danger)}.yat-workspace-danger form,/* Import is Export's twin: the same button, on the same row. The file input is
   still a file input — nothing else opens a picker — but it is behind its own
   label, which is the button. */
.yat-recurrence-form__note{margin:0;color:var(--sk-color-text-muted);font-size:.8rem}
.yat-import-form{display:contents}
.yat-import-button{display:inline-flex;align-items:center;gap:.4rem;cursor:pointer}
/* The input is visually hidden but still focusable, so the keyboard reaches it
   and has to be able to see where it is: the ring goes on the label, which is
   the thing on screen. */
.yat-import-form:focus-within .yat-import-button{outline:2px solid var(--sk-color-focus);outline-offset:2px}
.yat-import-form__chosen{flex-basis:100%;color:var(--sk-color-text-muted);font-size:.8rem}.yat-workspace-settings .yat-manage{margin-top:0}.yat-transfer-actions{display:flex;flex-wrap:wrap;align-items:center;gap:.75rem;margin-bottom:1rem}.yat-import-result{margin-bottom:1rem;padding:.75rem 1rem;border:1px solid var(--sk-color-border);border-radius:var(--sk-radius-md);background:var(--sk-color-surface-muted)}.yat-settings{display:grid;gap:1.5rem}.yat-settings>.sk-page-heading{margin-bottom:1rem}.yat-settings .sk-card{display:grid;gap:1rem;padding:clamp(1.5rem,4vw,2.25rem)}.yat-settings .sk-card>p{margin:0;color:var(--sk-color-text-muted)}.yat-settings form{display:grid;gap:1rem}.sk-page-heading__aside .sk-button{font-weight:500}.sk-page-heading__aside .sk-icon-button{color:var(--sk-color-text-muted)}.yat-notification-control{position:relative;display:inline-grid}.yat-tooltip{position:absolute;z-index:30;left:var(--yat-tooltip-left,50%);right:var(--yat-tooltip-right,auto);bottom:calc(100% + .5rem);width:max-content;max-width:min(17rem,calc(100vw - 2rem));padding:.45rem .6rem;border:1px solid var(--sk-color-border);border-radius:var(--sk-radius-sm);background:var(--sk-color-surface);box-shadow:var(--sk-component-shadow-panel);color:var(--sk-color-text);font-size:.75rem;line-height:1.35;opacity:0;pointer-events:none;transform:translate(var(--yat-tooltip-x,-50%),.2rem);transition:opacity 120ms,transform 120ms}.yat-notification-control:hover .yat-tooltip,.yat-notification-control:focus-within .yat-tooltip{opacity:1;transform:translate(var(--yat-tooltip-x,-50%),0)}.yat-notification-on,.yat-notification-off{display:grid}.yat-notification-off,#workspace-notification-toggle[aria-pressed=false] .yat-notification-on{display:none}#workspace-notification-toggle[aria-pressed=false] .yat-notification-off{display:grid}
.sk-workspace-dialogs{display:contents}
/* `will-change:transform` on the dragging row promotes it to its own layer up
   front. Without the hint, moving a row this wide (checkbox, title, actions,
   schedule form) by rewriting its transform on every pointer move is a
   repaint of that whole layer under Gecko's more conservative promotion
   heuristics — felt as the dragged row itself lagging behind the pointer,
   distinct from the ring's own cost. */
.yat-todo-region[data-sort-mode=true] .yat-todo[data-open=true]{cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none}.yat-todo-region[data-sort-mode=true] .yat-todo[data-open=true] .yat-toggle{display:none}.yat-todo-region[data-sort-mode=true] .yat-todo[data-open=true] .yat-todo__actions{opacity:0;pointer-events:none}.yat-todo-region[data-sort-mode=true] .yat-todo[data-open=true] .yat-note-indicator,.yat-todo-region[data-sort-mode=true] .yat-todo[data-open=true] .yat-checklist-indicator{pointer-events:none}.yat-todo-region[data-sort-mode=true] .yat-todo[data-open=true] .yat-drag-handle{opacity:.85}/* The half-second of hold, said out loud. Opening the sheet is what used to
   say the press had registered, and that has moved to the release — so without
   this the phone would feel like nothing happened until the finger came up. */
.yat-todo[data-yat-lifted=true]{background:var(--sk-color-active)}
@media(prefers-reduced-motion:no-preference){.yat-todo[data-yat-lifted=true]{transition:background 120ms}}
.yat-todo[data-dragging=true]{z-index:5;cursor:grabbing;box-shadow:var(--sk-component-shadow-panel);background:var(--sk-color-surface);border-radius:var(--sk-radius-md);will-change:transform}
.yat-todo[data-new=true]{animation:yat-new-todo 1.2s ease-out}.yat-todo[data-new=true]::after{content:"";position:absolute;inset:0 auto 0 0;width:2px;background:var(--sk-color-text-muted);animation:yat-new-edge 1.2s ease-out forwards}@keyframes yat-new-todo{0%{background:color-mix(in srgb,var(--sk-color-text) 11%,transparent)}100%{background:transparent}}@keyframes yat-new-edge{0%,55%{opacity:.75}100%{opacity:0}}.yat-todo[data-yat-rescheduled=true]{animation:yat-rescheduled 500ms ease-out}@keyframes yat-rescheduled{0%{background:color-mix(in srgb,var(--sk-color-accent) 16%,transparent)}100%{background:transparent}}@media(prefers-reduced-motion:reduce){.yat-todo[data-yat-rescheduled=true]{animation:none}}
/* A grid item refuses to shrink below its content unless told to, so without
   the minmax and the min-width a long name widens the row, the row widens the
   list, and the panel grows a horizontal scrollbar instead of an ellipsis. */
.yat-workspace-switcher{display:grid;grid-template-columns:minmax(0,1fr);gap:.15rem;margin:0;padding:0;list-style:none}
.yat-workspace-switcher>li{min-width:0}
.yat-workspace-switcher__item{display:flex;width:100%;min-height:var(--sk-size-touch);align-items:center;gap:.7rem;padding:.5rem .6rem;border:0;border-radius:var(--sk-radius-md);background:transparent;color:inherit;font:inherit;text-align:left;text-decoration:none;cursor:pointer}
.yat-workspace-switcher__item:hover{background:var(--sk-color-active)}
/* Selection is not focus here — the filter field holds that for the whole
   visit — so the chosen row has to look chosen on its own. */
.yat-workspace-switcher__item:focus,.yat-workspace-switcher__item[aria-selected=true]{background:var(--sk-color-active);outline:2px solid var(--sk-color-accent);outline-offset:-2px}
/* The switcher answers "where do I want to be" and gets out of the way: the
   page behind it is not dimmed, and above 48rem it sits high and narrow, near
   where the eye already is rather than square in the middle. */
#switch-workspaces::backdrop{background:transparent;backdrop-filter:none}
#switch-workspaces .sk-modal__body{overflow-x:hidden}
.yat-switcher__filter{width:100%;min-height:2.75rem;margin-bottom:.6rem;padding:0 .8rem;border:1px solid var(--sk-color-border);border-radius:var(--sk-radius-md);background:var(--sk-color-surface);color:var(--sk-color-text);font-size:1rem}
/* One icon in the list means one row indented past all the others, so the rows
   without one keep its place empty and every name starts on the same column. */
.yat-workspace-switcher__item:not(:has(.sk-icon))::before{content:"";flex:none;width:1.125rem}
/* The create row names nothing that needs lining up with the workspaces, so it
   keeps no gutter — and a <button> laid out as a flex box centres its own
   content unless told otherwise, which would leave "Create" mid-row. */
.yat-switcher__create form{display:contents}
.yat-switcher__create .yat-workspace-switcher__item{justify-content:flex-start;overflow:hidden}
.yat-switcher__create .yat-workspace-switcher__item::before{content:none}
/* The empty line is not a row to be chosen and must not look like one: no
   hover, no gutter, and the muted colour of something being said rather than
   offered. */
.yat-switcher__empty{padding:.5rem .6rem;color:var(--sk-color-text-muted);font-size:.85rem}
/* The hint rides on the selected row only: on every row it would be five
   copies of one instruction, and on none of them the key goes unmentioned. */
.yat-switcher__enter{display:none;flex:none;padding:.1rem .3rem;border:1px solid var(--sk-color-border);border-radius:var(--sk-radius-sm);color:var(--sk-color-text-muted);font-family:inherit;font-size:.65rem;letter-spacing:.02em}
.yat-workspace-switcher__item[aria-selected=true] .yat-switcher__enter{display:inline-block}
@media(min-width:48rem){#switch-workspaces{width:min(24rem,calc(100% - 2rem));max-height:calc(100dvh - 16vh);margin-block:12vh auto}#switch-workspaces .sk-modal__surface{max-height:calc(100dvh - 16vh)}}
/* Wider than the 32rem every other dialog gets. This one holds six sections,
   each with a note beside its title, and the label rows underneath — a name
   field, seven swatches and two buttons on one line. At 32rem it scrolled
   sideways to reach any of it. */
/* A fixed height, not just the cap every other dialog gets: each concern
   below is a <details>, and without this the dialog grew and shrank on every
   open and close of a section, jumping the whole panel around the toggle
   the visitor had just clicked. Held steady, only the body scrolls. */
@media(min-width:48rem){#workspace-settings{width:min(46rem,calc(100% - 2rem));height:min(36rem,calc(100dvh - 4rem))}#workspace-settings .sk-modal__surface{height:100%}}
/* An icon is a span too, so the label has to say it is not one — otherwise the
   icon takes the `flex:1` meant for the name and pushes it to the middle. */
.yat-workspace-switcher__item>span:not(.sk-icon){min-width:0;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.yat-workspace-switcher__badge{padding:.16rem .38rem;border-radius:999px;background:var(--sk-color-active);color:var(--sk-color-text-muted);font-size:.62rem;font-weight:700;letter-spacing:.03em;text-transform:uppercase}
.yat-workspace-switcher__count{display:inline-grid;min-width:1.25rem;height:1.25rem;padding:0 .25rem;place-items:center;border-radius:var(--sk-radius-pill);background:var(--sk-color-accent);color:var(--sk-color-on-accent);font-size:.65rem;font-weight:700}
.yat-todo-actions{display:contents}
.yat-todo-actions-overlay{position:fixed;inset:0;z-index:110;width:100%;height:100dvh;max-width:none;max-height:none;margin:0;padding:0;border:0;background:transparent;overflow:hidden}.yat-todo-actions-overlay::backdrop{background:color-mix(in srgb,var(--sk-color-text) 58%,transparent)}.yat-todo-actions-sheet{position:absolute;inset:auto 0 0;display:grid;max-height:min(80dvh,44rem);padding:.9rem max(.75rem,var(--sk-safe-right)) max(.75rem,var(--sk-safe-bottom)) max(.75rem,var(--sk-safe-left));border-radius:var(--sk-radius-xl) var(--sk-radius-xl) 0 0;background:var(--sk-color-surface);box-shadow:var(--sk-component-shadow-panel);overflow-y:auto}.yat-todo-actions-sheet h2{overflow:hidden;margin:.25rem .75rem .75rem;color:var(--sk-color-text-muted);font-family:var(--sk-font-display);font-size:.8rem;font-weight:600;line-height:1.3;text-overflow:ellipsis;white-space:nowrap}.yat-todo-actions-sheet__items{display:grid;gap:.15rem}.yat-todo-actions-sheet__items[hidden]{display:none}/* The chevron that says a row leads somewhere, and the one that says this
   row comes back. Pushed to the end of the row rather than beside the
   words, because it is about the sheet rather than about the task. */
.yat-todo-action-row__more{margin-left:auto;color:var(--sk-color-text-muted);font-size:1.1rem;line-height:1}
.yat-todo-action-row--back{color:var(--sk-color-text-muted);font-size:.85rem}
.yat-todo-action-row--back .yat-todo-action-row__more{margin-left:0;margin-right:.15rem}.yat-todo-actions-sheet__items>form{display:grid;gap:.15rem}.yat-todo-action-row,.yat-todo-action-row>button,.yat-todo-actions-cancel{display:flex;width:100%;min-height:var(--sk-size-touch);align-items:center;gap:.75rem;padding:.55rem .75rem;border:0;border-radius:var(--sk-radius-md);background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer}.yat-todo-action-row{padding:0}.yat-todo-action-row>input{display:none}.yat-todo-action-row:hover,.yat-todo-action-row>button:hover,.yat-todo-actions-cancel:hover{background:var(--sk-color-active)}.yat-todo-action-row--danger,.yat-todo-action-row--danger>button{color:var(--sk-color-danger)}.yat-todo-actions-cancel{justify-content:center;margin-top:.5rem;border-top:1px solid var(--sk-color-border);border-radius:0;font-weight:650}.yat-todo[data-actions-open=true]{z-index:3;background:var(--sk-color-active)}html[data-yat-actions-open=true],html[data-yat-actions-open=true] body{overflow:hidden}
/* Narrow-first defaults for the remaining desktop-shaped layouts. */
.yat-member-list li{flex-wrap:wrap}

@media(max-width:47.999rem){
.yat-page-heading{gap:.75rem}.yat-page-heading .sk-page-heading__lede{width:100%}.yat-page-heading .sk-page-heading__aside{width:100%;flex-wrap:nowrap;justify-content:flex-end;gap:.35rem}/* On a phone the aside is its own line under the title and its caption, so
   the view switch takes the left of that line and the bell and the cog keep
   the right. margin-right rather than space-between: where the workspace
   does not offer the switch, the icons stay where they were. */
.yat-page-heading .sk-page-heading__aside>.yat-view-switch{margin-right:auto}.yat-page-heading .sk-page-heading__aside .sk-icon-button{width:2.8rem;height:2.8rem}.yat-page-heading h1{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.yat-search{min-height:var(--sk-size-touch);justify-content:flex-end;margin-top:-1.25rem}.yat-search__field{display:none}.yat-search[data-expanded=true] .yat-search__field{display:flex;flex:1;padding-left:max(0rem,calc(3.5rem - var(--sk-gutter)))}.yat-search[data-expanded=true] .yat-search__actions{display:none}.yat-search-toggle__open,.yat-search-toggle__close{display:grid}.yat-search-toggle__close,.yat-search[data-expanded=true] .yat-search-toggle__open{display:none}.yat-search[data-expanded=true] .yat-search-toggle__close{display:grid}.yat-search input{font-size:1rem}.yat-search__actions .yat-filter-chip{width:var(--sk-size-touch);padding:0;justify-content:center}.yat-search__actions .yat-filter-chip span:not(.sk-icon){display:none}
.yat-todo-list{margin-right:calc(var(--sk-gutter) * -1);margin-left:calc(var(--sk-gutter) * -1);border-right:0;border-left:0;border-radius:0}.yat-todo{min-height:3.65rem;padding:.35rem .3rem;padding-top:calc(.35rem + var(--yat-time-caption,0rem))}.yat-todo__meta{margin-top:.15rem}.yat-waiting>.yat-todo-list,.yat-frozen>.yat-todo-list,.yat-archive>.yat-todo-list{border-right:0;border-left:0}
.yat-todo[data-actions-open=true] .yat-todo__actions{display:none}
}
/* The desktop widening: everything below here is the exception. */
@media(min-width:48rem){
/* The composer is the search field at this width, so the shell keeps only the
   filter chips and the magnifier has nothing left to open. */
.yat-search{justify-content:flex-end}.yat-search__field{display:none}
.yat-search [data-yat-search-toggle]{display:none}
.yat-todo-actions-overlay{display:none}
.yat-member-list li{flex-wrap:nowrap}

}
/* Terseness, not layout: below 30rem the filter chips keep their icons and drop
   their labels rather than pushing the search field out of the row. */
@media(max-width:30rem){.yat-filter-chip span:not(.sk-icon){display:none}}
.yat-search input::-webkit-search-cancel-button{-webkit-appearance:none;appearance:none;display:none}
button.yat-todo-action-row{padding:.55rem .75rem}
@media(forced-colors:active){.yat-todo-list,.sk-card{border:1px solid CanvasText}.yat-check__box{forced-color-adjust:auto}}
.yat-member-avatar{overflow:hidden}.yat-member-avatar img,.yat-todo__avatar img{width:100%;height:100%;object-fit:cover}
.yat-todo[hidden],.yat-waiting[hidden],.yat-frozen[hidden],.yat-archive[hidden]{display:none}
.yat-waiting,.yat-frozen,.yat-archive{display:grid;gap:.6rem}

/* A recorded interval reads as a sentence, so that is what the list shows; the
   fields arrive in its place when one is being corrected. Both states are one
   row high, and both wrap rather than overflow on a phone. */
.yat-time-entry-list{display:grid;gap:.35rem;padding:0;margin:0;list-style:none}
.yat-time-entry{border-bottom:1px solid color-mix(in srgb,var(--sk-color-border) 60%,transparent)}
.yat-time-entry:last-child{border-bottom:0}
.yat-time-entry__view{display:flex;min-height:2.75rem;flex-wrap:wrap;align-items:center;gap:.5rem}
.yat-time-entry__reading{font-variant-numeric:tabular-nums}
.yat-time-entry__note{flex:1;min-width:0;overflow:hidden;color:var(--sk-color-text-muted);font-size:.85rem;text-overflow:ellipsis;white-space:nowrap}
.yat-time-entry__view>.sk-icon-button{margin-left:auto}
.yat-time-entry__edit{display:flex;flex-wrap:wrap;align-items:center;gap:.4rem;padding:.35rem 0 .6rem}
.yat-time-entry__edit .sk-field{flex:1;min-width:8.5rem}
.yat-time-entry__edit .sk-field input{min-height:2.5rem;padding:.35rem .55rem}
.yat-time-entry__actions{display:flex;gap:.25rem}

/* Both answers to an invitation, side by side: declining is an answer too. */
.yat-invitation-actions{display:flex;flex-wrap:wrap;gap:.6rem;margin-top:1rem}

/* A task's conversation. The icon is the signal: outlined when there is
   nothing new, solid when there is, and the count beside it says how much
   there is to read at all. */
.yat-message-link{text-decoration:none}
/* The indicator sits in the meta line, where it is visible without hovering —
   an unread message nobody can see is not a signal. */
/* The row's whole surface is the completion toggle, and the body lets clicks
   through to it; an indicator that can be pressed has to take them back. */
.yat-message-indicator{pointer-events:auto;position:relative;z-index:2;display:inline-flex;align-items:center;gap:.25rem;padding:.1rem .4rem;border-radius:var(--sk-radius-pill);color:var(--sk-color-text-muted);font-size:.72rem;font-weight:650;text-decoration:none}
.yat-message-indicator:hover{background:var(--sk-color-active);color:var(--sk-color-text)}
.yat-message-indicator[data-unread=true]{background:var(--sk-color-accent);color:var(--sk-color-on-accent)}
.yat-messages-panel{display:grid;gap:.75rem}
.yat-messages{display:grid;gap:.75rem;padding:0;margin:0;list-style:none;max-height:22rem;overflow-y:auto}
.yat-message{display:grid;gap:.15rem}
.yat-message__head{display:flex;flex-wrap:wrap;align-items:baseline;gap:.5rem}
.yat-message__head time{color:var(--sk-color-text-muted);font-size:.75rem}
.yat-message__body{margin:0;overflow-wrap:anywhere;white-space:pre-wrap}
.yat-message__edited{color:var(--sk-color-text-muted);font-size:.7rem;font-style:italic}
/* The two verbs on one's own message. Out of the way until the message is
   under the pointer or has the focus inside it, because most of the time a
   conversation is something to read rather than to tidy. */
.yat-message__actions{display:flex;margin-left:auto;gap:.1rem;opacity:0;transition:opacity 120ms}
.yat-message:hover .yat-message__actions,.yat-message:focus-within .yat-message__actions{opacity:1}
.yat-message__actions button{display:inline-grid;width:1.5rem;height:1.5rem;padding:0;place-items:center;border:0;border-radius:var(--sk-radius-sm);background:transparent;color:var(--sk-color-text-muted);cursor:pointer}
.yat-message__actions button:hover{background:var(--sk-color-active);color:var(--sk-color-text)}
.yat-message__actions form{display:flex}
.yat-message__cancel{flex:none;padding:0 .6rem;border:0;border-radius:var(--sk-radius-md);background:transparent;color:var(--sk-color-text-muted);font:inherit;font-size:.8rem;cursor:pointer}
/* A touch screen has no hover to reveal them with. */
@media(hover:none){.yat-message__actions{opacity:1}}
.yat-messages__empty{margin:0;color:var(--sk-color-text-muted)}
/* A task that went somewhere else says so, and offers the way there. The
   anchor is pushed to the far end of the toast because the sentence is the
   news and the link is the response to it. Styled here rather than in the ui
   package: the toast is shared, but this action is YAT's own, and the
   stylesheet that draws it should be the one that ships with it. */
.sk-toast__action{margin-left:auto;flex:none;color:var(--sk-color-accent);font-weight:600;text-decoration:none;white-space:nowrap}
.sk-toast__action:hover{text-decoration:underline}
/* The sentence under a settings field that explains what the field is for,
   as opposed to what it is called. */
.yat-settings-hint{margin:.35rem 0 0;color:var(--sk-color-text-muted);font-size:.8rem}
.yat-settings-hint code{padding:0 .2rem;border-radius:var(--sk-radius-sm);background:var(--sk-color-active);font-family:var(--sk-font-mono,ui-monospace,monospace)}
