/* ============================================================================
   Life Command Center — UI primitives
   Bottom sheet · toast · progress ring · check row
   ========================================================================== */

@layer components {

  /* ======================================================== BOTTOM SHEET ===
     Built on <dialog>, so the browser supplies the top layer, the focus
     trap, background inertness, and Esc. */

  .sheet {
    /* Reset the UA dialog box entirely — it is a full-viewport stage here,
       and the panel inside it is the actual sheet. */
    position: fixed;
    inset: 0;
    width: 100%;
    max-width: 100%;
    height: 100%;
    max-height: 100%;
    margin: 0;
    padding: 0;
    border: none;
    background: transparent;
    overflow: hidden;
  }

  /* Opacity is bound to --sheet-progress, which the drag handler writes on
     every pointermove. The room dims as the sheet rises, rather than the
     scrim snapping on at the end. */
  .sheet::backdrop {
    background: var(--scrim);
    opacity: var(--sheet-progress, 0);
  }

  .sheet.is-animating::backdrop {
    transition: opacity var(--dur-slow) var(--ease-out);
  }

  .sheet__panel {
    position: absolute;
    inset: auto 0 0 0;

    display: flex;
    flex-direction: column;
    max-height: 100%;

    background: var(--surface-1);
    border-radius: var(--radius-sheet) var(--radius-sheet) 0 0;
    box-shadow: var(--elev-sheet);

    /* The home-indicator gap belongs inside the sheet, not under it. */
    padding-block-end: var(--safe-bottom);

    /* Promotes to its own layer so dragging never triggers a repaint of the
       page behind — this is what keeps the drag at 60fps on a mid-range
       Android device. */
    will-change: transform;

    outline: none;
    overscroll-behavior: contain;
  }

  /* Transitions are applied ONLY between gestures. During a drag the
     transform is written directly, so the panel tracks the finger exactly
     instead of easing toward it. */
  .sheet.is-animating .sheet__panel {
    transition: transform var(--dur-slow) var(--ease-spring);
  }

  /* --- grip ------------------------------------------------------------- */
  .sheet__grip {
    display: grid;
    place-items: center;
    padding-block: var(--space-3) var(--space-1);
    flex: none;
    cursor: grab;

    /* Hands the vertical gesture to our pointer handler. Without this the
       browser would claim it for scrolling and the drag would not start. */
    touch-action: none;
  }

  .sheet__grip:active { cursor: grabbing; }

  .sheet__handle {
    width: 2.25rem;
    height: 0.3125rem;
    background: var(--border-strong);
    border-radius: var(--radius-full);
  }

  /* --- header ----------------------------------------------------------- */
  .sheet__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    flex: none;

    padding: var(--space-2) var(--space-5) var(--space-4);
    touch-action: none;
  }

  .sheet__title {
    font-size: var(--text-lg);
    font-weight: var(--weight-semi);
    letter-spacing: var(--tracking-tight);
  }

  .sheet__close {
    display: grid;
    place-items: center;
    width: var(--tap-min);
    height: var(--tap-min);
    margin-inline-end: calc(var(--space-2) * -1);

    color: var(--text-tertiary);
    background: var(--surface-2);
    border-radius: var(--radius-full);

    transition: transform var(--dur-instant) var(--ease-out),
                color var(--dur-fast) var(--ease-out);
  }

  .sheet__close svg { width: 1.125rem; height: 1.125rem; }
  .sheet__close:hover { color: var(--text-primary); }
  .sheet__close:active { transform: scale(0.9); }

  /* --- body ------------------------------------------------------------- */
  .sheet__body {
    flex: 1 1 auto;
    min-height: 0;
    padding-inline: var(--space-5);
    padding-block-end: var(--space-4);

    overflow-y: auto;
    -webkit-overflow-scrolling: touch;

    /* Stops a scroll that reaches the end from chaining to the page behind. */
    overscroll-behavior: contain;

    /* touch-action is set from JS: 'pan-y' when the content scrolls,
       'none' when it fits (so the whole sheet becomes draggable). */
  }

  /* --- footer ----------------------------------------------------------- */
  /* Pinned below the scroll region: the primary action stays under the thumb
     no matter how long the form is. */
  .sheet__footer {
    flex: none;
    display: grid;
    gap: var(--space-2);
    padding: var(--space-4) var(--space-5) var(--space-2);
    background: var(--surface-1);
    border-top: 1px solid var(--border-subtle);
  }

  /* --- page scroll lock -------------------------------------------------- */
  /* iOS ignores overflow:hidden for touch scrolling, so the page is pinned.
     --locked-scroll preserves the position, restored on close. */
  html.is-sheet-open,
  html.is-sheet-open body {
    overflow: hidden;
  }

  html.is-sheet-open body {
    position: fixed;
    inset-block-start: var(--locked-scroll, 0);
    inset-inline: 0;
    width: 100%;
  }

  @media (min-width: 768px) {
    /* On desktop the sheet becomes a centred, rounded panel — the bottom
       anchoring exists for thumbs and has no purpose with a mouse. */
    .sheet__panel {
      inset: auto 50% 0 auto;
      translate: 50% 0;
      width: min(32rem, 100%);
      border-radius: var(--radius-2xl) var(--radius-2xl) 0 0;
    }
  }

  /* ========================================================= THEME TOGGLE ===
     Three-way segmented control: Light / System / Dark.

     Lives here rather than in auth.css because every page renders it — while
     it sat in the login stylesheet it fell back to raw radio inputs on the
     dashboard, gallery and settings screens. */

  .skin-picker {
    display: inline-flex;
    gap: 2px;
    padding: 3px;
    border: 0;
    background: var(--surface-2);
    border-radius: var(--radius-full);
    box-shadow: inset 0 0 0 1px var(--border-subtle);
  }

  .skin-picker__option { position: relative; display: inline-flex; }

  .skin-picker__input { position: absolute; opacity: 0; pointer-events: none; }

  .skin-picker__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    color: var(--text-tertiary);
    border-radius: var(--radius-full);
    cursor: pointer;
    transition:
      color var(--dur-fast) var(--ease-out),
      background-color var(--dur-fast) var(--ease-out),
      transform var(--dur-instant) var(--ease-out);
  }

  .skin-picker__btn:hover { color: var(--text-secondary); }
  .skin-picker__btn:active { transform: scale(0.9); }

  .skin-picker__input:checked + .skin-picker__btn {
    color: var(--text-primary);
    background: var(--surface-1);
    box-shadow: var(--elev-1);
  }

  .skin-picker__input:focus-visible + .skin-picker__btn {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
  }

  /* ================================================================ TOAST ===
     Above the tab bar, in the thumb zone — a top-anchored toast on a phone
     is both unreachable and under the notch. */

  .toast-host {
    position: fixed;
    z-index: var(--z-toast);
    inset-block-end: calc(var(--tabbar-height) + var(--safe-bottom) + var(--space-3));
    inset-inline: max(var(--space-4), var(--safe-left)) max(var(--space-4), var(--safe-right));

    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    align-items: center;

    pointer-events: none;
  }

  .toast {
    pointer-events: auto;
    display: flex;
    align-items: center;
    gap: var(--space-3);

    width: 100%;
    max-width: 26rem;
    min-height: var(--tap-min);
    padding: var(--space-3) var(--space-4);

    font-size: var(--text-sm);
    line-height: var(--leading-snug);

    color: var(--text-primary);
    background: var(--surface-1);
    border-radius: var(--radius-lg);
    box-shadow: var(--elev-3);

    animation: toast-in var(--dur-base) var(--ease-spring) both;
    transition: transform var(--dur-fast) var(--ease-out),
                opacity var(--dur-fast) var(--ease-out);
  }

  .toast--success { color: var(--success); }
  .toast--error   { color: var(--danger); }

  .toast__icon { flex: none; width: 1.125rem; height: 1.125rem; }

  .toast__message {
    flex: 1 1 auto;
    color: var(--text-primary);
    text-wrap: pretty;
  }

  .toast__action {
    flex: none;
    min-height: 2rem;
    padding-inline: var(--space-3);
    margin-inline-end: calc(var(--space-2) * -1);

    font-size: var(--text-sm);
    font-weight: var(--weight-semi);
    color: var(--accent);
    border-radius: var(--radius-md);
  }

  .toast__action:active { transform: scale(0.94); }

  .toast.is-leaving { animation: toast-out var(--dur-fast) var(--ease-in) both; }

  @keyframes toast-in {
    from { opacity: 0; translate: 0 16px; scale: 0.96; }
    to   { opacity: 1; translate: 0 0;    scale: 1; }
  }

  @keyframes toast-out {
    from { opacity: 1; translate: 0 0;   scale: 1; }
    to   { opacity: 0; translate: 0 8px; scale: 0.97; }
  }

  /* Desktop: bottom-left, clear of the FAB. */
  @media (min-width: 768px) {
    .toast-host {
      inset-block-end: var(--space-6);
      inset-inline: calc(5.5rem + var(--space-6)) auto;
      align-items: flex-start;
    }
    .toast { width: 24rem; }
  }

  /* ========================================================= PROGRESS RING === */

  .ring {
    position: relative;
    display: inline-grid;
    place-items: center;
    width: var(--ring-size);
    height: var(--ring-size);
  }

  .ring__svg { transform: rotate(-90deg); }   /* start the sweep at 12 o'clock */

  .ring__track { stroke: var(--ring-track); }

  .ring__arc {
    stroke: var(--accent);
    transition: stroke-dashoffset var(--dur-slower) var(--ease-out),
                stroke var(--dur-base) var(--ease-out);
  }

  .ring--success .ring__arc { stroke: var(--success); }
  .ring--warn    .ring__arc { stroke: var(--warn); }
  .ring--danger  .ring__arc { stroke: var(--danger); }

  .ring__center {
    position: absolute;
    display: grid;
    place-items: center;
    gap: 1px;
    text-align: center;
  }

  .ring__value {
    font-size: var(--text-metric);
    font-weight: var(--weight-bold);
    line-height: 1;
    letter-spacing: var(--tracking-tight);
  }

  .ring__suffix {
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
    color: var(--text-tertiary);
  }

  .ring__label {
    margin-block-start: var(--space-1);
    font-size: var(--text-2xs);
    font-weight: var(--weight-semi);
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    color: var(--text-tertiary);
  }

  /* ============================================================ CHECK ROW === */

  .check-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    width: 100%;

    /* Comfortably past the 44px minimum: this is the control the user hits
       most, often while walking. */
    min-height: 3.25rem;
    padding: var(--space-2) var(--space-1);

    text-align: start;
    border-radius: var(--radius-lg);

    transition: background-color var(--dur-fast) var(--ease-out),
                transform var(--dur-instant) var(--ease-out);
  }

  .check-row:active { transform: scale(0.985); }

  .check-row__box {
    position: relative;
    flex: none;
    display: grid;
    place-items: center;

    width: 1.625rem;
    height: 1.625rem;

    color: var(--text-on-accent);
    border: 2px solid var(--border-strong);
    border-radius: var(--radius-sm);

    transition: background-color var(--dur-fast) var(--ease-out),
                border-color var(--dur-fast) var(--ease-out),
                scale var(--dur-base) var(--ease-spring);
  }

  .check-row.is-checked .check-row__box {
    background: var(--accent);
    border-color: var(--accent);
  }

  .check-row--success.is-checked .check-row__box {
    background: var(--success);
    border-color: var(--success);
  }

  /* The tick is DRAWN rather than revealed. On iOS Safari, which exposes no
     vibration API, this animation is the only feedback the user gets — so it
     has to read as a deliberate response, not a state swap. */
  .check-row__tick {
    width: 1.125rem;
    height: 1.125rem;
  }

  .check-row__tick-path {
    stroke-dasharray: 24;
    stroke-dashoffset: 24;
    transition: stroke-dashoffset var(--dur-base) var(--ease-out);
  }

  .check-row.is-checked .check-row__tick-path {
    stroke-dashoffset: 0;
  }

  /* Expanding ring on completion — the visual equivalent of a haptic tap. */
  .check-row__box::after {
    content: "";
    position: absolute;
    inset: -2px;
    border: 2px solid var(--accent);
    border-radius: var(--radius-sm);
    opacity: 0;
    pointer-events: none;
  }

  .check-row.is-celebrating .check-row__box::after {
    animation: check-glow var(--dur-slower) var(--ease-out);
  }

  .check-row.is-celebrating .check-row__box {
    scale: 1.08;
  }

  @keyframes check-glow {
    from { opacity: 0.9; scale: 1; }
    to   { opacity: 0;   scale: 1.9; }
  }

  .check-row__text {
    flex: 1 1 auto;
    display: grid;
    gap: 1px;
    min-width: 0;
  }

  .check-row__label {
    font-size: var(--text-base);
    font-weight: var(--weight-medium);
    transition: color var(--dur-base) var(--ease-out);
  }

  .check-row.is-checked .check-row__label {
    color: var(--text-tertiary);
    text-decoration: line-through;
    text-decoration-color: var(--border-strong);
    text-decoration-thickness: 1.5px;
  }

  .check-row__detail {
    font-size: var(--text-sm);
    color: var(--text-tertiary);
  }

  /* Unsynced state: a quiet pip, not a blocking spinner. The action already
     succeeded from the user's point of view. */
  .check-row__status {
    flex: none;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: var(--radius-full);
    background: var(--warn);
    opacity: 0;
    transition: opacity var(--dur-base) var(--ease-out);
  }

  .check-row.is-pending .check-row__status {
    opacity: 1;
    animation: pulse 1.4s var(--ease-inout) infinite;
  }

  @keyframes pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.35; }
  }
}
