@import "tailwindcss";
@import "tom-select/dist/css/tom-select.css";

/*
 * App palette, matching sakeus.fi: the cool default "neutral" scale is remapped
 * to the site's warm "beige" scale, so every existing neutral-* utility picks
 * up the brand tone with no markup churn. CGA accents are exposed for sparing use.
 */
@theme {
  --color-neutral-50: oklch(96.5% 0.003 67.83);
  --color-neutral-100: oklch(93.9% 0.004 56.5);
  --color-neutral-200: oklch(87.8% 0.007 67.75);
  --color-neutral-300: oklch(78.4% 0.016 67.59);
  --color-neutral-400: oklch(69.1% 0.019 72.99);
  --color-neutral-500: oklch(60% 0.02 71);
  --color-neutral-600: oklch(50.9% 0.021 69.98);
  --color-neutral-700: oklch(41.5% 0.02 70.16);
  --color-neutral-800: oklch(32.5% 0.018 73);
  --color-neutral-900: oklch(23.4% 0.015 76.14);
  --color-neutral-950: oklch(17.7% 0.014 71.76);

  --color-cga-cyan: oklch(83.68% 0.1431 193.65);
  --color-cga-pink: oklch(68.38% 0.2139 0.41);
  --color-cga-yellow: oklch(87.7% 0.1581 96.99);
  --color-cga-gray: oklch(33.75% 0.0035 286.21);
}

@layer components {
  .form-input {
    @apply block w-full rounded-md border border-neutral-300 bg-white px-3 py-2 text-sm text-neutral-900 placeholder-neutral-400 focus:border-neutral-900 focus:outline-none focus:ring-1 focus:ring-neutral-900;
  }

  /* Native selects: replace the inconsistent UA caret with a custom chevron,
     vertically centered and clear of the text. Tom Select pickers hide their
     underlying <select>, so this only affects the plain ones. */
  select.form-input {
    @apply appearance-none bg-no-repeat pr-9;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='%23a8a094'%3E%3Cpath d='M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z'/%3E%3C/svg%3E");
    background-position: right 0.625rem center;
    background-size: 1rem 1rem;
  }

  /* Progressive enhancement: where the customizable <select> is supported
     (Chrome/Edge 135+), upgrade native selects to a fully branded control with
     a styled drop-down rendered in the top layer. Everywhere else they keep the
     chevron above and open the standard OS dropdown. */
  @supports (appearance: base-select) {
    select.form-input,
    select.form-input::picker(select) {
      appearance: base-select;
    }

    /* base-select turns the control into a button; lay it out as a flex row so
       the selected content sits left and the picker icon stays pinned right.
       (form-input's `display: block` would otherwise drop the icon below.) */
    select.form-input {
      @apply flex items-center justify-between gap-2 pr-3;
      background-image: none;
    }

    select.form-input::picker-icon {
      content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 256 256' fill='%23a8a094'%3E%3Cpath d='M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z'/%3E%3C/svg%3E");
      @apply block h-4 w-4;
      transform-origin: center;
      transition: rotate 0.2s ease;
    }

    select.form-input:open::picker-icon {
      rotate: 180deg;
    }

    select.form-input::picker(select) {
      @apply mt-1 rounded-md border border-neutral-200 bg-white p-1 shadow-lg;
    }

    select.form-input option {
      @apply flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-neutral-900;
    }

    select.form-input option:hover {
      @apply bg-neutral-100;
    }

    select.form-input option:checked {
      @apply font-medium;
    }

    select.form-input option::checkmark {
      @apply text-neutral-900;
    }

    /* Calendar user picker: an initials avatar leads each option and mirrors
       into the closed trigger via <selectedcontent>. The initials come from a
       data attribute (not a text node) so non-supporting browsers, which
       flatten options to text, show only the name. */
    select.user-select selectedcontent {
      @apply flex items-center gap-2;
    }

    select.user-select .avatar {
      @apply flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-neutral-200 text-[0.625rem] font-semibold uppercase leading-none text-neutral-700;
    }

    select.user-select .avatar::before {
      content: attr(data-initials);
    }
  }

  .form-label {
    @apply text-xs font-medium uppercase tracking-wider text-neutral-600;
  }

  .btn {
    @apply inline-flex cursor-pointer items-center justify-center rounded-md bg-neutral-900 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-neutral-700 focus:outline-none focus:ring-2 focus:ring-neutral-900 focus:ring-offset-2;
  }

  .btn-secondary {
    @apply inline-flex cursor-pointer items-center justify-center rounded-md border border-neutral-300 bg-white px-4 py-2 text-sm font-medium text-neutral-700 transition-colors hover:bg-neutral-100 focus:outline-none focus:ring-2 focus:ring-neutral-900 focus:ring-offset-2;
  }

  .action-menu-item {
    @apply block w-full cursor-pointer px-4 py-2 text-left text-sm text-neutral-700 transition-colors hover:bg-neutral-50;
  }

  .card {
    @apply rounded-xl border border-neutral-200 bg-white shadow-sm;
  }

  .page-title {
    @apply text-2xl font-semibold tracking-tight text-neutral-900;
  }

  /* Segmented entry bar: a full-height cell whose borderless control lights up
   * on focus, since the cell has no border to indicate it otherwise. */
  .bar-cell {
    @apply flex h-14 items-center border-neutral-200 focus-within:bg-neutral-50 focus-within:ring-1 focus-within:ring-inset focus-within:ring-neutral-900;
  }

  /* Washes a cell whose field failed validation in pink (background only). */
  .bar-cell--error {
    @apply bg-cga-pink/15;
  }

  .bar-input {
    @apply h-full border-0 bg-transparent text-sm text-neutral-900 placeholder-neutral-400 focus:outline-none focus:ring-0;
  }

  /* Compact field label shown only above the stacked mobile bar cells. */
  .bar-label {
    @apply text-[10px] font-medium uppercase leading-none tracking-wide text-neutral-500;
  }
}

/*
 * Flash messages are overlaid (absolutely positioned) at the top of the content
 * area, so they slide in over the page without shifting layout. They drop down
 * from the top edge while fading in, and reverse out when dismissed. Entry uses
 * @starting-style (fires on first render and on each Turbo navigation); exit is
 * driven by the .flash--leaving class the flash Stimulus controller adds before
 * removing the node.
 */
.flash {
  opacity: 1;
  translate: 0;
  transition: opacity 0.3s ease-out, translate 0.3s ease-out;
}

@starting-style {
  .flash {
    opacity: 0;
    translate: 0 -100%;
  }
}

.flash--leaving {
  opacity: 0;
  translate: 0 -100%;
}

@media (prefers-reduced-motion: reduce) {
  .flash {
    translate: none;
    transition-duration: 0.1s;
  }

  @starting-style {
    .flash {
      translate: none;
    }
  }

  .flash--leaving {
    translate: none;
  }
}

/*
 * Mobile navigation drawer: a left-pinned, full-height top-layer Popover. It
 * slides in from the edge while its ::backdrop dims the page, with discrete
 * transitions (display/overlay) so the slide-out animates on close too. Opened
 * only by the md:hidden hamburger, so it never appears on desktop.
 */
.mobile-drawer {
  margin: 0;
  inset: 0 auto 0 0;
  height: 100dvh;
  width: min(18rem, 82vw);
  border: 0;
  transform: translateX(-100%);
  transition: transform 0.3s ease, overlay 0.3s allow-discrete, display 0.3s allow-discrete;
}

.mobile-drawer:popover-open {
  display: flex;
  flex-direction: column;
  transform: translateX(0);
}

@starting-style {
  .mobile-drawer:popover-open {
    transform: translateX(-100%);
  }
}

.mobile-drawer::backdrop {
  background: rgb(0 0 0 / 0.4);
  opacity: 0;
  transition: opacity 0.3s ease, overlay 0.3s allow-discrete, display 0.3s allow-discrete;
}

.mobile-drawer:popover-open::backdrop {
  opacity: 1;
}

@starting-style {
  .mobile-drawer:popover-open::backdrop {
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .mobile-drawer,
  .mobile-drawer::backdrop {
    transition: none;
  }
}

/* Compact time fields: drop the native clock icon / picker dropdown so the
 * start–end range stays tight and is edited inline via the field segments. */
.time-field::-webkit-calendar-picker-indicator {
  display: none;
}

/*
 * Tom Select overrides to match the monochrome form theme. Kept unlayered so
 * they win over Tom Select's own (unlayered) base styles.
 */
.ts-wrapper.single .ts-control,
.ts-wrapper.single .ts-control input {
  @apply text-sm text-neutral-900;
}

/* Strip the copied form-input border/padding so only the inner control frames the field. */
.ts-wrapper.form-input {
  @apply border-0 p-0 shadow-none;
}

/* Borderless variant: the project picker reads as one of the bar's inputs (a
 * placeholder you can type into) rather than a framed button. Fills its bar
 * cell so the full-height dividers frame it, with a clean inset ring on focus —
 * carried by the control itself so it isn't clipped behind the white field. */
.ts-wrapper.project-select {
  @apply h-full w-full;
}

.ts-wrapper.project-select .ts-control {
  @apply flex h-full cursor-text items-center rounded-none border-0 px-3 ring-0 hover:bg-neutral-50;
}

.ts-wrapper.project-select.focus .ts-control {
  @apply ring-1 ring-inset ring-neutral-900 hover:bg-transparent;
}

.ts-wrapper .ts-control {
  @apply min-h-0 rounded-md border border-neutral-300 bg-white px-3 py-2 shadow-none;
}

.ts-wrapper.focus .ts-control {
  @apply border-neutral-900 ring-1 ring-neutral-900;
}

.ts-wrapper .ts-control input::placeholder {
  @apply text-neutral-400;
}

/* The project cell's Tom Select control paints its own background over the
   cell, so tint the control directly when that cell failed validation. The
   :hover pairing matches the control's own high-specificity hover rule. */
.bar-cell--error .ts-wrapper.project-select .ts-control,
.bar-cell--error .ts-wrapper.project-select .ts-control:hover {
  @apply bg-cga-pink/15;
}

.ts-dropdown {
  @apply mt-1 rounded-md border border-neutral-200 text-sm text-neutral-900 shadow-lg;
}

.ts-dropdown .optgroup-header {
  @apply bg-white px-3 py-1 text-xs font-semibold uppercase tracking-wider text-neutral-600;
}

.ts-dropdown .option {
  @apply px-3 py-2;
}

.ts-dropdown .option.active {
  @apply bg-neutral-900 text-white;
}

/*
 * Minutes step picker: a top-layer Popover so it is never clipped by the form
 * row. Where CSS anchor positioning is supported it tethers to its trigger and
 * flips to stay inside the viewport; elsewhere it falls back to the UA-centered
 * top-layer position (visible, just not anchored).
 */
.minutes-popover {
  margin: 0;
}

/*
 * Mobile: the steps render inline as a chip row inside the field. The popover
 * attribute is inert here (the trigger is hidden), so force the row visible
 * (overriding the UA `[popover]:not(:popover-open){display:none}`) and undo the
 * UA top-layer box (`position:fixed; inset:0`) that would otherwise float the
 * row out of the field to the top of the viewport.
 */
@media (max-width: 1023.98px) {
  .minutes-popover {
    display: flex;
    position: static;
    inset: auto;
  }
}

/*
 * Desktop: behave as an anchored top-layer popover menu, hidden until opened —
 * the segmented bar has no room for the full chip row. Each form instance
 * tethers its popover to its own trigger via inline anchor-name/position-anchor.
 */
@media (min-width: 1024px) {
  .minutes-popover {
    min-width: 4rem;
  }

  .minutes-popover:not(:popover-open) {
    display: none;
  }

  .minutes-popover:popover-open {
    display: flex;
    flex-direction: column;
  }
}

@supports (anchor-name: --a) {
  @media (min-width: 1024px) {
    .minutes-popover {
      position: fixed;
      inset: auto;
      position-area: block-end span-inline-start;
      position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
      margin-block: 0.25rem;
    }
  }
}

/*
 * Row action menu (kebab, shared/_action_menu partial): a top-layer Popover, so
 * it escapes the row's clipping and stacking. Anchored below its trigger and
 * aligned to the trigger's inline-end (the menu hangs to the left of the dots),
 * flipping above when tight.
 */
.action-menu {
  margin: 0;
}

.action-menu:popover-open {
  display: flex;
  flex-direction: column;
}

@supports (anchor-name: --a) {
  .action-menu {
    position: fixed;
    inset: auto;
    position-area: block-end span-inline-start;
    position-try-fallbacks: flip-block;
    margin-block: 0.25rem;
  }
}
