/* The app. Colour comes from theme.css and nowhere else; this file is layout,
   rhythm and motion. */

@layer components {
  /* ── frame ─────────────────────────────────────────────────────────── */
  body {
    /* The composer is fixed to the bottom and changes height as it is used, so
       the list's clearance is measured from it (app.js) rather than guessed.
       The fallback is the closed height, for the moment before script runs. */
    --composer-h: 4.75rem;
    min-height: 100dvh;
  }

  .skip {
    position: fixed;
    inset-block-start: 0.5rem;
    inset-inline-start: 0.5rem;
    z-index: 5;
    padding: 0.5rem 0.9rem;
    border-radius: var(--r-sm);
    background: var(--raised);
    box-shadow: var(--lift-high);
    translate: 0 -160%;
    transition: translate var(--step) var(--ease);
  }

  .skip:focus {
    translate: 0 0;
  }

  .bar {
    position: sticky;
    inset-block-start: 0;
    z-index: 3;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    min-height: var(--bar-h);
    padding: calc(env(safe-area-inset-top, 0px) + 0.25rem) max(1rem, env(safe-area-inset-right, 0px))
      0.25rem max(1rem, env(safe-area-inset-left, 0px));
    background: color-mix(in oklch, var(--ground) 82%, transparent);
    backdrop-filter: blur(14px) saturate(1.4);
    border-block-end: 1px solid var(--edge);
  }

  .bar h1 {
    font-size: 0.82rem;
    font-weight: 600;
    letter-spacing: 0.17em;
    text-transform: uppercase;
    color: var(--quiet);
  }

  .bar-tools {
    display: flex;
    align-items: center;
    gap: 0.15rem;
  }

  .sync {
    margin-inline-end: 0.4rem;
    font-size: 0.75rem;
    color: var(--faint);
    font-variant-numeric: tabular-nums;
  }

  .sync[data-state="off"] {
    color: var(--later);
  }

  /* ── buttons ───────────────────────────────────────────────────────── */
  .icon {
    display: grid;
    place-items: center;
    /* A 44px target even though the glyph is 19px. */
    inline-size: 2.75rem;
    block-size: 2.75rem;
    border: 0;
    border-radius: var(--r-full);
    background: none;
    color: var(--quiet);
    cursor: pointer;
    transition: background var(--step), color var(--step);
  }

  .icon:hover {
    background: var(--sunken);
    color: var(--ink);
  }

  .primary,
  .ghost {
    padding: 0.62rem 1.15rem;
    border: 1px solid transparent;
    border-radius: var(--r-md);
    font-weight: 600;
    cursor: pointer;
  }

  .primary {
    background: var(--accent);
    color: var(--accent-ink);
  }

  .ghost {
    background: none;
    border-color: var(--edge-strong);
    color: var(--ink);
  }

  .ghost.danger {
    border-color: transparent;
    color: var(--danger);
  }

  :where(.primary, .ghost, .icon):disabled {
    opacity: 0.45;
    cursor: default;
  }

  /* The theme button's glyph becomes a moon by biting a hole out of the sun. */
  #theme .sun {
    opacity: 1;
    transition: opacity var(--step) var(--ease);
  }

  #theme .orb {
    transition: scale var(--step) var(--ease);
  }

  :root[data-theme="dark"] #theme .sun {
    opacity: 0;
  }

  :root[data-theme="dark"] #theme .orb {
    scale: 1.35;
  }

  /* ── the list ──────────────────────────────────────────────────────── */
  main {
    max-width: 44rem;
    margin-inline: auto;
    padding: 0.5rem max(1rem, env(safe-area-inset-right, 0px))
      calc(var(--composer-h) + env(safe-area-inset-bottom, 0px) + 2rem)
      max(1rem, env(safe-area-inset-left, 0px));
  }

  .empty {
    margin-block: 4rem;
    text-align: center;
    color: var(--quiet);
    text-wrap: balance;
  }

  .empty strong {
    display: block;
    color: var(--ink);
  }

  .region {
    margin-block-start: 1.6rem;
  }

  /* A region with nothing in it says nothing. */
  .region:not(:has(li)) {
    display: none;
  }

  .region h2 {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-block-end: 0.5rem;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.13em;
    text-transform: uppercase;
    color: var(--quiet);
  }

  .dot {
    inline-size: 0.5rem;
    block-size: 0.5rem;
    border-radius: var(--r-full);
    background: var(--lane, var(--quiet));
  }

  .region[data-region="now"] {
    --lane: var(--now);
  }

  .region[data-region="soon"] {
    --lane: var(--soon);
  }

  .region[data-region="later"] {
    --lane: var(--later);
  }

  .count {
    margin-inline-start: auto;
    font-weight: 500;
    letter-spacing: normal;
    color: var(--faint);
  }

  .region ul,
  .drawer ul {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
  }

  /* ── a pill ────────────────────────────────────────────────────────── */
  .pill {
    display: flex;
    /* A long title makes a tall pill; the controls belong to the whole row,
       so they sit at its top rather than floating in the middle of it. */
    align-items: start;
    gap: 0.75rem;
    padding: 0.7rem 0.75rem 0.7rem 0.95rem;
    border: 1px solid var(--edge);
    border-radius: var(--r-md);
    background: var(--raised);
    box-shadow: var(--lift);
    /* Named for view transitions so a move between regions is animated. */
    view-transition-name: var(--vt);
    view-transition-class: pill;
  }

  .pill:hover {
    border-color: var(--edge-strong);
  }

  .pill.is-pending {
    opacity: 0.6;
  }

  .pill-main {
    flex: 1;
    min-inline-size: 0;
    border: 0;
    padding: 0;
    background: none;
    text-align: start;
    cursor: pointer;
  }

  .pill-title {
    display: block;
    overflow-wrap: anywhere;
    text-wrap: pretty;
  }

  .pill.is-blocked .pill-title {
    color: var(--quiet);
  }

  .pill-meta {
    display: flex;
    flex-wrap: wrap;
    /* A reason can be 200 characters with no spaces in them. */
    overflow-wrap: anywhere;
    align-items: center;
    gap: 0.1rem 0.5rem;
    margin-block-start: 0.15rem;
    font-size: 0.79rem;
    color: var(--quiet);
  }

  .pill-meta .blocked {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.05rem 0.4rem 0.05rem 0.3rem;
    border: 1px solid var(--edge);
    border-radius: var(--r-full);
  }

  .pill-meta .overdue {
    color: var(--later);
    font-weight: 600;
  }

  .pill-meta svg {
    display: inline-block;
    vertical-align: -0.12em;
  }

  .pin {
    color: var(--soon);
  }

  /* The circle. The hit area is the whole 44px square; the ring is 22px. */
  .tick {
    display: grid;
    place-items: center;
    flex: none;
    align-self: start;
    inline-size: 2.75rem;
    block-size: 2.75rem;
    margin: -0.5rem -0.35rem -0.5rem 0;
    border: 0;
    background: none;
    border-radius: var(--r-full);
    cursor: pointer;
  }

  .tick::before {
    content: "";
    inline-size: 1.35rem;
    block-size: 1.35rem;
    border: 2px solid var(--edge-strong);
    border-radius: var(--r-full);
    transition: border-color var(--step), background var(--step), scale var(--step) var(--ease);
  }

  .tick:hover::before {
    border-color: var(--lane, var(--accent));
  }

  .tick:active::before {
    scale: 0.88;
  }

  .drawer .tick::before {
    border-color: var(--quiet);
    background: var(--quiet);
  }

  /* The done pill's circle carries a tick, not just a fill. */
  .drawer .tick::after {
    content: "";
    position: absolute;
    inline-size: 0.42rem;
    block-size: 0.72rem;
    border: solid var(--raised);
    border-width: 0 2px 2px 0;
    rotate: 45deg;
    translate: 0 -0.07rem;
  }

  .drawer .tick {
    position: relative;
  }

  .more {
    display: grid;
    place-items: center;
    flex: none;
    align-self: start;
    inline-size: 2.75rem;
    block-size: 2.75rem;
    margin: -0.5rem -0.35rem -0.5rem 0;
    border: 0;
    border-radius: var(--r-full);
    background: none;
    color: var(--faint);
    cursor: pointer;
    opacity: 0.6;
    transition: opacity var(--step), color var(--step);
  }

  .pill:hover .more,
  .more:focus-visible,
  .more[aria-expanded="true"],
  .pill:has(.pill-main:focus-visible) .more {
    opacity: 1;
    color: var(--quiet);
  }

  /* ── done drawer ───────────────────────────────────────────────────── */
  .drawer {
    margin-block-start: 2rem;
    border-block-start: 1px solid var(--edge);
    padding-block-start: 0.75rem;
  }

  .drawer:not(:has(li)) {
    display: none;
  }

  .drawer summary {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding-block: 0.4rem;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.13em;
    text-transform: uppercase;
    color: var(--quiet);
    cursor: pointer;
  }

  .drawer summary::marker {
    content: "";
  }

  .drawer summary::before {
    content: "";
    inline-size: 0.4rem;
    block-size: 0.4rem;
    border-right: 1.8px solid currentColor;
    border-bottom: 1.8px solid currentColor;
    rotate: -45deg;
    transition: rotate var(--step) var(--ease);
  }

  .drawer[open] summary::before {
    rotate: 45deg;
  }

  .drawer ul {
    padding-block-start: 0.5rem;
  }

  .drawer .pill {
    background: none;
    box-shadow: none;
    border-style: dashed;
  }

  .drawer .pill-title {
    color: var(--quiet);
    text-decoration: line-through;
    text-decoration-color: var(--faint);
  }

  /* ── composer ──────────────────────────────────────────────────────── */
  .composer {
    position: fixed;
    inset-block-end: 0;
    inset-inline: 0;
    z-index: 4;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    /* Full-bleed like the header; only the controls inside are held to the
       column width, so the two pieces of fixed chrome agree with each other. */
    padding: 0.7rem max(1rem, env(safe-area-inset-right, 0px))
      calc(0.7rem + env(safe-area-inset-bottom, 0px)) max(1rem, env(safe-area-inset-left, 0px));
    background: color-mix(in oklch, var(--ground) 86%, transparent);
    backdrop-filter: blur(14px) saturate(1.4);
    border-block-start: 1px solid var(--edge);
  }

  .composer-line,
  .composer-more {
    max-inline-size: 44rem;
    margin-inline: auto;
    inline-size: 100%;
  }

  .composer-line {
    display: flex;
    gap: 0.5rem;
    align-items: center;
  }

  .composer input[type="text"] {
    flex: 1;
    min-inline-size: 0;
    padding: 0.75rem 0.95rem;
    border: 1px solid var(--edge-strong);
    border-radius: var(--r-md);
    background: var(--raised);
    transition: border-color var(--step), box-shadow var(--step);
  }

  .composer input[type="text"]:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px color-mix(in oklch, var(--accent) 22%, transparent);
  }

  .go {
    display: grid;
    place-items: center;
    flex: none;
    inline-size: 2.85rem;
    block-size: 2.85rem;
    border: 0;
    border-radius: var(--r-md);
    background: var(--accent);
    color: var(--accent-ink);
    cursor: pointer;
    transition: opacity var(--step), scale var(--step) var(--ease);
  }

  .go:active {
    scale: 0.94;
  }

  /* The extra fields are out of the way until the composer is in use — and
     `:has()` means that is a CSS fact, not a JS one. */
  .composer-more {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 0.75rem;
    align-items: center;
    font-size: 0.85rem;
    color: var(--quiet);
    /* interpolate-size lets height:auto animate. */
    block-size: 0;
    overflow: hidden;
    opacity: 0;
    transition: block-size var(--step) var(--ease), opacity var(--step);
  }

  .composer:focus-within .composer-more,
  .composer:has(#title:not(:placeholder-shown)) .composer-more {
    block-size: auto;
    opacity: 1;
  }

  .composer-more input[type="date"],
  .composer-more input[type="time"] {
    padding: 0.35rem 0.5rem;
    border: 1px solid var(--edge);
    border-radius: var(--r-sm);
    background: var(--raised);
    color: var(--ink);
  }

  .check:has(:disabled) {
    opacity: 0.5;
    cursor: default;
  }

  .check {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    cursor: pointer;
  }

  /* ── sheets ────────────────────────────────────────────────────────── */
  .sheet {
    margin: auto;
    padding: 0;
    inline-size: min(30rem, calc(100vw - 2rem));
    max-block-size: min(46rem, calc(100dvh - 2rem));
    border: 1px solid var(--edge);
    border-radius: var(--r-lg);
    background: var(--raised);
    color: var(--ink);
    box-shadow: var(--lift-high);
  }

  .sheet::backdrop {
    background: var(--scrim);
    backdrop-filter: blur(3px);
  }

  .sheet,
  .sheet::backdrop {
    transition: opacity var(--step) var(--ease), translate var(--step) var(--ease), overlay
        var(--step) allow-discrete, display var(--step) allow-discrete;
    opacity: 0;
  }

  .sheet[open],
  .sheet[open]::backdrop {
    opacity: 1;
  }

  @starting-style {
    .sheet[open],
    .sheet[open]::backdrop {
      opacity: 0;
    }
  }

  .sheet-form {
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
    padding: 1rem 1.15rem 1.15rem;
  }

  .sheet header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-inline-end: -0.5rem;
  }

  .sheet h2 {
    font-size: 1.05rem;
  }

  .sheet header .icon {
    font-size: 1.5rem;
    line-height: 1;
  }

  .sheet footer {
    position: sticky;
    inset-block-end: -1.15rem;
    display: flex;
    justify-content: space-between;
    gap: 0.75rem;
    margin-block-start: 0.35rem;
    padding-block: 0.6rem;
    /* The form scrolls under this on a short screen, so it needs a ground of
       its own and an edge to show there is more above. */
    background: var(--raised);
    box-shadow: 0 -1px 0 var(--edge);
  }

  .field {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    border: 0;
    padding: 0;
    min-inline-size: 0;
  }

  .field > span,
  .field legend {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--quiet);
    padding: 0;
  }

  .field :where(input, textarea) {
    padding: 0.6rem 0.75rem;
    border: 1px solid var(--edge-strong);
    border-radius: var(--r-sm);
    background: var(--ground);
    inline-size: 100%;
  }

  .field textarea {
    resize: vertical;
    min-block-size: 3.5rem;
  }

  .row {
    display: flex;
    gap: 0.75rem;
  }

  .row .field {
    flex: 1;
  }

  /* ── lane / segmented pickers ──────────────────────────────────────── */
  .lanes {
    display: flex;
    gap: 0.4rem;
  }

  .lanes label {
    flex: 1;
  }

  .lanes input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
  }

  .lanes span,
  .lanes label {
    display: block;
  }

  .lanes label > span,
  .lanes button {
    display: block;
    inline-size: 100%;
    padding: 0.45rem 0.5rem;
    border: 1px solid var(--edge-strong);
    border-radius: var(--r-sm);
    background: var(--ground);
    font-size: 0.85rem;
    text-align: center;
    cursor: pointer;
    transition: background var(--step), border-color var(--step), color var(--step);
  }

  .lanes label:has(:checked) > span,
  .lanes button[aria-pressed="true"] {
    border-color: var(--lane, var(--accent));
    background: color-mix(in oklch, var(--lane, var(--accent)) 16%, transparent);
    color: var(--ink);
    font-weight: 600;
  }

  .lanes label:has(:focus-visible) > span {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
  }

  [data-lane="now"] {
    --lane: var(--now);
  }

  [data-lane="soon"] {
    --lane: var(--soon);
  }

  [data-lane="later"] {
    --lane: var(--later);
  }

  /* ── the pill menu ─────────────────────────────────────────────────── */
  .menu {
    position: absolute;
    margin: 0;
    inline-size: 13rem;
    padding: 0.4rem;
    border: 1px solid var(--edge);
    border-radius: var(--r-md);
    background: var(--raised);
    box-shadow: var(--lift-high);
    /* Anchor positioning where it exists; the fallback is a JS-placed box. */
    position-anchor: --pill;
    position-area: block-end span-inline-start;
    position-try-fallbacks: flip-block, flip-inline;
    margin-block-start: 0.35rem;
  }

  .menu,
  .menu::backdrop {
    transition: opacity var(--step) var(--ease), overlay var(--step) allow-discrete, display
        var(--step) allow-discrete;
    opacity: 0;
  }

  .menu:popover-open {
    opacity: 1;
  }

  @starting-style {
    .menu:popover-open {
      opacity: 0;
    }
  }

  .menu > button {
    inline-size: 100%;
    padding: 0.55rem 0.6rem;
    border: 0;
    border-radius: var(--r-sm);
    background: none;
    text-align: start;
    font-size: 0.9rem;
    cursor: pointer;
  }

  .menu > button:hover {
    background: var(--sunken);
  }

  .menu > button.danger {
    color: var(--danger);
  }

  .menu .lanes {
    margin-block-end: 0.35rem;
  }

  /* ── toast ─────────────────────────────────────────────────────────── */
  .toast {
    position: fixed;
    inset-block-end: calc(var(--composer-h) + env(safe-area-inset-bottom, 0px) + 1rem);
    inset-inline: 0;
    z-index: 6;
    display: flex;
    justify-content: center;
    pointer-events: none;
  }

  .toast:empty {
    display: none;
  }

  .toast > span {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    max-inline-size: calc(100dvw - 2rem - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px));
    padding: 0.6rem 0.7rem 0.6rem 1rem;
    border-radius: var(--r-full);
    background: var(--inverse);
    color: var(--inverse-ink);
    box-shadow: var(--lift-high);
    font-size: 0.88rem;
    pointer-events: auto;
    animation: rise var(--step) var(--ease);
  }

  .toast button {
    border: 0;
    border-radius: var(--r-full);
    padding: 0.25rem 0.7rem;
    background: color-mix(in oklch, currentColor 18%, transparent);
    color: inherit;
    font-weight: 600;
    cursor: pointer;
  }

  @keyframes rise {
    from {
      opacity: 0;
      translate: 0 0.75rem;
    }
  }
}

@layer utilities {
  /* Wider than a phone: the composer's extra fields are always visible, since
     there is room and it saves a focus step. */
  @media (min-width: 40rem) {
    .composer-more {
      block-size: auto;
      opacity: 1;
    }
  }

  /* A pill leaving the list slides out rather than blinking away. */
  ::view-transition-group(.pill) {
    animation-duration: 0.22s;
  }

  ::view-transition-old(.pill) {
    animation: fade-out 0.18s var(--ease) both;
  }

  ::view-transition-new(.pill) {
    animation: fade-in 0.18s var(--ease) both;
  }

  @keyframes fade-out {
    to {
      opacity: 0;
      scale: 0.97;
    }
  }

  @keyframes fade-in {
    from {
      opacity: 0;
    }
  }
}
