/* ==========================================================================
   POKIT DESIGN SYSTEM
   --------------------------------------------------------------------------
   Source of truth: pokit-ui.html

   This file is purely additive. It introduces the Pokit tokens as CSS
   custom properties, a small `pk-*` component vocabulary used by the
   restyled templates, and a layer of global polish that upgrades existing
   markup without renaming a single hook that JavaScript or htmx relies on.

   All global element rules are written with :where() so they carry zero
   specificity and can never out-rank a Tailwind utility that a template
   deliberately applied.
   ========================================================================== */

:root {
  --pk-coral: #F4845F;
  --pk-coral-600: #E26A43;
  --pk-coral-50: #FEF4EF;
  --pk-coral-100: #FDE5DA;
  --pk-coral-200: #FAC8B4;
  --pk-sand: #C9A487;
  --pk-sand-50: #FAF6F2;
  --pk-mint: #7ECBB4;
  --pk-mint-600: #5BB298;
  --pk-mint-50: #EFF9F6;
  --pk-ink: #262626;
  --pk-ink-700: #454545;
  --pk-ink-500: #6B6B6B;
  --pk-ink-400: #8E8E8E;
  --pk-ink-300: #BDBDBD;
  --pk-ink-200: #E4E4E2;
  --pk-ink-100: #F1F1EF;
  --pk-canvas: #FCFCFA;
  --pk-gradient: linear-gradient(90deg, #F4845F 0%, #C9A487 50%, #7ECBB4 100%);
  --pk-shadow-soft: 0 1px 2px rgba(38, 38, 38, .04), 0 4px 16px rgba(38, 38, 38, .06);
  --pk-shadow-lift: 0 2px 4px rgba(38, 38, 38, .04), 0 12px 32px rgba(38, 38, 38, .10);
  --pk-shadow-glow: 0 0 0 4px rgba(244, 132, 95, .15);

  /* DaisyUI-compatible surface tokens, consumed by the `base-*` Tailwind colours
     as `rgb(var(...) / <alpha-value>)`. Stored as bare RGB triplets for that to
     work. ~60 legacy `bg-base-*` / `text-base-content` usages resolve through
     these, and they flip automatically in dark mode. */
  --pk-base-100: 255 255 255;      /* card surface      */
  --pk-base-200: 252 252 250;      /* canvas            */
  --pk-base-300: 228 228 226;      /* border / raised   */
  --pk-base-content: 38 38 38;     /* body text         */
}

.dark {
  --pk-base-100: 38 38 38;         /* ink-900           */
  --pk-base-200: 26 26 24;         /* ink-950           */
  --pk-base-300: 70 70 68;         /* border / raised   */
  --pk-base-content: 228 228 226;  /* ink-200           */
}

/* Native <dialog> safety net.
   The browser hides a closed dialog with `dialog:not([open]) { display: none }`
   from its UA stylesheet, but that is only a UA rule: any author utility such as
   `flex` or `grid` on the dialog element out-ranks it and leaves the closed modal
   permanently painted over the page. This restores the expected behaviour with
   higher specificity (0,1,1) than a plain `.flex` (0,1,0), so a dialog is hidden
   until it is actually opened. `showModal()`, the `open` attribute and inline
   `style.display` all keep working.
   Note: no `dialog[open]` rule is set on purpose - several dialogs lay themselves
   out with margin auto / their own display, and forcing flex on all of them would
   change their geometry. Dialogs that want flex centering opt in with `open:flex`. */
dialog:not([open]) {
  display: none;
}

/* --------------------------------------------------------------------------
   Global polish
   -------------------------------------------------------------------------- */

/* NOTE: `html { scroll-behavior: smooth }` is deliberately NOT set globally.
   The style guide has it, but applying it here would change how every existing
   programmatic scroll in the app behaves (chat auto-scroll, scrollIntoView on
   validation errors, anchor jumps). The chat pane already opts in on its own. */

:where(body) {
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

::selection {
  background: var(--pk-coral-100);
  color: var(--pk-ink);
}

/* Warm, thin scrollbars everywhere (replaces the browser default grey).
   Pseudo-elements cannot live inside :where(), so these stay plain. */
:where(*) {
  scrollbar-width: thin;
  scrollbar-color: var(--pk-ink-200) transparent;
}

::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: var(--pk-ink-200);
  border-radius: 999px;
}

::-webkit-scrollbar-thumb:hover {
  background: var(--pk-ink-300);
}

.dark ::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, .12);
}

/* Form controls: Pokit rounding + coral focus glow.
   :where() keeps specificity at zero so any Tailwind utility still wins. */
:where(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="color"]):not([type="submit"]):not([type="button"]),
  select,
  textarea) {
  border-radius: 0.75rem;
}

:where(input, select, textarea):focus {
  outline: none;
}

:where(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="color"])):focus,
:where(select):focus,
:where(textarea):focus {
  border-color: var(--pk-coral);
  box-shadow: var(--pk-shadow-glow);
}

/* The chat composer opts out of the rule above entirely. Its textarea sits inside a
   surface that draws its own border, so the app-wide coral focus ring landed as a
   second orange ring right around the caret. Excluding it by selector is deliberate:
   an override declared later loses the specificity fight against `focus:ring-*`
   utilities, whereas never matching cannot. */
:where(textarea.pk-plain-focus):focus,
:where(input.pk-plain-focus):focus {
  border-color: inherit !important;
  box-shadow: none !important;
}

:where(input, textarea)::placeholder {
  color: var(--pk-ink-300);
}
/* Native controls pick up the brand colour. */
:where(input[type="checkbox"], input[type="radio"], input[type="range"], progress) {
  accent-color: var(--pk-coral);
}

/* Keyboard focus stays visible for accessibility, in brand colour. */
:where(a, button, [role="button"], summary):focus-visible {
  outline: 2px solid var(--pk-coral);
  outline-offset: 2px;
  border-radius: 0.5rem;
}

/* Smooth, restrained motion on interactive chrome. */
:where(button, a, [role="button"]) {
  transition-property: background-color, border-color, color, box-shadow, opacity, transform;
  transition-duration: 150ms;
  transition-timing-function: cubic-bezier(.4, 0, .2, 1);
}

/* Anchors default to the brand colour when a template didn't style them. */
.dark :where(a) {
  color: inherit;
}

/* --------------------------------------------------------------------------
   Brand helpers
   -------------------------------------------------------------------------- */

.text-pokit {
  background: var(--pk-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.bg-pokit {
  background: var(--pk-gradient);
}

.border-pokit {
  border: 1.5px solid transparent;
  background:
    linear-gradient(#fff, #fff) padding-box,
    var(--pk-gradient) border-box;
}

.dark .border-pokit {
  background:
    linear-gradient(#262626, #262626) padding-box,
    var(--pk-gradient) border-box;
}

.shadow-soft {
  box-shadow: var(--pk-shadow-soft);
}

.shadow-lift {
  box-shadow: var(--pk-shadow-lift);
}

.shadow-glow {
  box-shadow: var(--pk-shadow-glow);
}

@keyframes pk-blob {

  0%,
  100% {
    transform: translate(0, 0) scale(1);
  }

  50% {
    transform: translate(1px, -1px) scale(1.05);
  }
}

.animate-blob {
  animation: pk-blob 4s ease-in-out infinite;
}

@keyframes pk-dots {

  0%,
  80%,
  100% {
    opacity: .25;
  }

  40% {
    opacity: 1;
  }
}

.typing span {
  animation: pk-dots 1.2s infinite;
}

.typing span:nth-child(2) {
  animation-delay: .15s;
}

.typing span:nth-child(3) {
  animation-delay: .3s;
}

/* --------------------------------------------------------------------------
   Transient notifications: #toast-container and #llm-status
   --------------------------------------------------------------------------
   Both slots live inside one fixed "notification rail" in base.html (see the
   markup there). They are styled by *id* here because several callers rewrite
   the element's own class attribute - #llm-status in particular is written to
   from dozens of streaming status paths.

   #toast-container uses display:contents so its toasts become direct children of
   the shared rail; that way toasts and status messages stack in one column and
   can never sit on top of each other. */

#toast-container {
  display: contents;
}

#llm-status {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  width: 100%;
  min-width: 0;
}

/* Collapse completely when there is nothing to show, so the rail is inert. */
#llm-status:empty {
  display: none;
}

#toast-container>*,
#llm-status>* {
  width: 100%;
  max-width: 100%;
  min-width: 0;
  pointer-events: auto;
}

@media (min-width: 640px) {

  #toast-container>*,
  #llm-status>* {
    width: auto;
  }
}

/* --------------------------------------------------------------------------
   pk-* COMPONENTS
   Used by the restyled templates. Everything here is opt-in.
   ========================================================================== */

/* ── Cards & surfaces ───────────────────────────────────────────────────── */

.pk-card {
  background: #fff;
  border: 1px solid var(--pk-ink-200);
  border-radius: 1rem;
  box-shadow: var(--pk-shadow-soft);
}

.pk-card-lg {
  border-radius: 1.5rem;
}

.pk-card-hover {
  transition: border-color .2s, box-shadow .2s, transform .2s;
}

.pk-card-hover:hover {
  border-color: var(--pk-coral-200, #FAC8B4);
  box-shadow: var(--pk-shadow-lift);
}

.pk-surface {
  background: var(--pk-canvas);
  border: 1px solid var(--pk-ink-200);
  border-radius: 1rem;
}

.dark .pk-card,
.dark .pk-surface {
  background: #262626;
  border-color: rgba(255, 255, 255, .08);
}

/* ── Buttons ────────────────────────────────────────────────────────────── */

.pk-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  padding: .625rem 1rem;
  border-radius: .75rem;
  font-size: .8125rem;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
  cursor: pointer;
  border: 1px solid transparent;
  background: transparent;
  color: var(--pk-ink);
  transition: background-color .15s, border-color .15s, color .15s, box-shadow .15s, transform .15s;
}

.pk-btn:active {
  transform: scale(.98);
}

.pk-btn:disabled,
.pk-btn[disabled] {
  opacity: .5;
  cursor: not-allowed;
  transform: none;
}

.pk-btn-primary {
  background: var(--pk-coral);
  color: #fff;
  box-shadow: 0 1px 2px rgba(38, 38, 38, .06);
}

.pk-btn-primary:hover {
  background: var(--pk-coral-600);
}

.pk-btn-grad {
  background: var(--pk-gradient);
  color: #fff;
  box-shadow: 0 1px 2px rgba(38, 38, 38, .06);
}

.pk-btn-grad:hover {
  filter: brightness(1.04);
}

.pk-btn-secondary {
  background: #fff;
  border-color: var(--pk-ink-200);
  color: var(--pk-ink);
}

.pk-btn-secondary:hover {
  background: var(--pk-ink-100);
}

.dark .pk-btn-secondary {
  background: transparent;
  border-color: rgba(255, 255, 255, .12);
  color: #E4E4E2;
}

.dark .pk-btn-secondary:hover {
  background: rgba(255, 255, 255, .06);
}

.pk-btn-ghost {
  color: var(--pk-ink-700);
}

.pk-btn-ghost:hover {
  background: var(--pk-ink-100);
}

.dark .pk-btn-ghost {
  color: #BDBDBD;
}

.dark .pk-btn-ghost:hover {
  background: rgba(255, 255, 255, .06);
}

.pk-btn-deploy {
  background: var(--pk-mint);
  color: #fff;
  box-shadow: 0 1px 2px rgba(38, 38, 38, .06);
}

.pk-btn-deploy:hover {
  background: var(--pk-mint-600);
}

.pk-btn-danger {
  background: #fff;
  border-color: #FECACA;
  color: #DC2626;
}

.pk-btn-danger:hover {
  background: #FEF2F2;
}

.pk-btn-icon {
  width: 2.5rem;
  height: 2.5rem;
  padding: 0;
  border-radius: .75rem;
  border-color: var(--pk-ink-200);
}

.pk-btn-sm {
  padding: .4rem .7rem;
  font-size: .75rem;
  border-radius: .6rem;
}

.pk-btn-lg {
  padding: .75rem 1.25rem;
  font-size: .875rem;
}

/* ── Inputs ─────────────────────────────────────────────────────────────── */

.pk-input {
  width: 100%;
  padding: .625rem .875rem;
  border-radius: .75rem;
  border: 1px solid var(--pk-ink-200);
  background: #fff;
  color: var(--pk-ink);
  font-size: .875rem;
}

.pk-input::placeholder {
  color: var(--pk-ink-300);
}

.pk-input:focus {
  outline: none;
  border-color: var(--pk-coral);
  box-shadow: var(--pk-shadow-glow);
}

.dark .pk-input {
  background: #1A1A18;
  border-color: rgba(255, 255, 255, .10);
  color: #F1F1EF;
}

.pk-label {
  display: block;
  font-size: .8125rem;
  font-weight: 500;
  color: var(--pk-ink);
  margin-bottom: .375rem;
}

.dark .pk-label {
  color: #E4E4E2;
}

.pk-hint {
  font-size: .75rem;
  color: var(--pk-ink-400);
  margin-top: .25rem;
}

/* ── Badges / status pills ──────────────────────────────────────────────── */

.pk-badge {
  display: inline-flex;
  align-items: center;
  gap: .375rem;
  padding: .25rem .625rem;
  border-radius: 999px;
  font-size: .75rem;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
}

.pk-badge-live {
  background: var(--pk-mint-50);
  color: #428C76;
}

.pk-badge-build {
  background: var(--pk-sand-50);
  color: #8A6A52;
}

.pk-badge-draft {
  background: var(--pk-coral-50);
  color: #BC5332;
}

.pk-badge-fail {
  background: #FEF2F2;
  color: #DC2626;
}

.pk-badge-muted {
  background: var(--pk-ink-100);
  color: var(--pk-ink-500);
}

/* Dark mode: pastel 50-shade backgrounds are far too bright on an ink surface,
   so the pills switch to a translucent tint of their accent colour. */
.dark .pk-badge-live {
  background: rgba(126, 203, 180, .16);
  color: #9AD7C5;
}

.dark .pk-badge-build {
  background: rgba(201, 164, 135, .18);
  color: #DCC4AF;
}

.dark .pk-badge-draft {
  background: rgba(244, 132, 95, .16);
  color: #F9B49A;
}

.dark .pk-badge-fail {
  background: rgba(239, 68, 68, .16);
  color: #FCA5A5;
}

.dark .pk-alert-success {
  background: rgba(126, 203, 180, .12);
  border-color: rgba(126, 203, 180, .30);
  color: #DAF1EA;
}

.dark .pk-alert-warn {
  background: rgba(201, 164, 135, .12);
  border-color: rgba(201, 164, 135, .30);
  color: #F2E9E0;
}

.dark .pk-alert-error {
  background: rgba(239, 68, 68, .12);
  border-color: rgba(239, 68, 68, .30);
  color: #FEE2E2;
}

.dark .pk-alert-info {
  background: rgba(244, 132, 95, .12);
  border-color: rgba(244, 132, 95, .30);
  color: #FDE5DA;
}

.dark .pk-badge-muted {
  background: rgba(255, 255, 255, .08);
  color: #BDBDBD;
}

.pk-dot {
  width: .375rem;
  height: .375rem;
  border-radius: 999px;
  flex-shrink: 0;
}

.pk-dot-live {
  background: var(--pk-mint);
}

.pk-dot-build {
  background: var(--pk-sand);
}

.pk-dot-draft {
  background: var(--pk-coral);
}

.pk-dot-fail {
  background: #EF4444;
}

.pk-chip {
  display: inline-flex;
  align-items: center;
  padding: .125rem .5rem;
  border-radius: .375rem;
  background: var(--pk-ink-100);
  color: var(--pk-ink-700);
  font-size: .75rem;
}

.dark .pk-chip {
  background: rgba(255, 255, 255, .08);
  color: #E4E4E2;
}

.pk-kbd {
  display: inline-flex;
  align-items: center;
  padding: .125rem .5rem;
  border-radius: .375rem;
  border: 1px solid var(--pk-ink-200);
  color: var(--pk-ink-500);
  font-size: .75rem;
  font-family: "JetBrains Mono", ui-monospace, monospace;
}

/* ── Avatars ────────────────────────────────────────────────────────────── */

.pk-avatar {
  display: grid;
  place-items: center;
  border-radius: 999px;
  font-weight: 700;
  color: #fff;
  background: var(--pk-gradient);
  flex-shrink: 0;
}

.pk-avatar-soft {
  background: var(--pk-mint-100);
  color: #428C76;
}

/* ── Alerts ─────────────────────────────────────────────────────────────── */

.pk-alert {
  display: flex;
  gap: .75rem;
  padding: .875rem;
  border-radius: .75rem;
  font-size: .8125rem;
  border: 1px solid transparent;
}

.pk-alert-success {
  background: var(--pk-mint-50);
  border-color: #B6E3D5;
}

.pk-alert-warn {
  background: var(--pk-sand-50);
  border-color: #E5D3C2;
}

.pk-alert-error {
  background: #FEF2F2;
  border-color: #FECACA;
}

.pk-alert-info {
  background: var(--pk-coral-50);
  border-color: #FAC8B4;
}

/* ── Empty states ───────────────────────────────────────────────────────── */

.pk-empty {
  display: grid;
  place-items: center;
  text-align: center;
  padding: 2rem 1.5rem;
}

.pk-empty-mark {
  width: 3.5rem;
  height: 3.5rem;
  border-radius: 1rem;
  background: var(--pk-ink-100);
  display: grid;
  place-items: center;
  margin: 0 auto .75rem;
}

.dark .pk-empty-mark {
  background: rgba(255, 255, 255, .08);
}

/* ── Skeleton / loading ─────────────────────────────────────────────────── */

.pk-skel {
  background: var(--pk-ink-100);
  border-radius: .375rem;
  animation: pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;
}

.dark .pk-skel {
  background: rgba(255, 255, 255, .08);
}

.pk-progress {
  height: .375rem;
  border-radius: 999px;
  background: var(--pk-ink-100);
  overflow: hidden;
}

.pk-progress>span {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--pk-gradient);
}

/* ── Code / log panels ──────────────────────────────────────────────────── */

.pk-code {
  background: var(--pk-ink);
  color: rgba(255, 255, 255, .9);
  border-radius: .75rem;
  overflow: hidden;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: .8125rem;
}

.pk-code-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: .5rem 1rem;
  background: rgba(255, 255, 255, .05);
  color: rgba(255, 255, 255, .6);
  font-size: .75rem;
}

/* ── Toast ──────────────────────────────────────────────────────────────── */

.pk-toast {
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: .75rem 1rem;
  border-radius: .75rem;
  background: var(--pk-ink);
  color: #fff;
  font-size: .8125rem;
  box-shadow: var(--pk-shadow-lift);
}

/* ── Chat bubbles ───────────────────────────────────────────────────────── */

.pk-bubble-user {
  background: var(--pk-coral);
  color: #fff;
  border-radius: 1rem 1rem .375rem 1rem;
  box-shadow: 0 1px 2px rgba(38, 38, 38, .06);
}

.pk-bubble-ai {
  background: #fff;
  border: 1px solid var(--pk-ink-200);
  border-radius: 1rem 1rem 1rem .375rem;
  box-shadow: 0 1px 2px rgba(38, 38, 38, .06);
}

.dark .pk-bubble-ai {
  background: #262626;
  border-color: rgba(255, 255, 255, .08);
}

/* ── Section headings ───────────────────────────────────────────────────── */

.pk-eyebrow {
  font-size: .75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--pk-ink-400);
  margin-bottom: .5rem;
}

.pk-page-title {
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--pk-ink);
}

.dark .pk-page-title {
  color: #F1F1EF;
}

.pk-muted {
  color: var(--pk-ink-500);
  font-size: .8125rem;
}

/* -- Chat loader -------------------------------------------------------------
   The design's typing indicator: a gently drifting logo plus three dots that
   pulse in sequence (coral / sand / mint). Lifted verbatim from pokit-ui.html. */
@keyframes pk-blob {
    0%, 100% { transform: translate(0, 0) scale(1); }
    50%      { transform: translate(1px, -1px) scale(1.05); }
}
.pk-animate-blob { animation: pk-blob 4s ease-in-out infinite; }

@keyframes pk-dots {
    0%, 80%, 100% { opacity: .25; }
    40%           { opacity: 1; }
}
.pk-typing span { animation: pk-dots 1.2s infinite; }
.pk-typing span:nth-child(2) { animation-delay: .15s; }
.pk-typing span:nth-child(3) { animation-delay: .3s; }

/* Focus opt-out. The rule above is deliberately global - it gives every field in the
   app a coral focus ring - but the chat composer is a special case: its textarea sits
   inside a surface that already draws the coral border on focus-within, so the extra
   coral box-shadow here shows up as a second orange ring right around the caret.
   Zero specificity, declared after the global rule, so it wins on source order. */
:where(.pk-plain-focus):focus {
  border-color: inherit;
  box-shadow: none;
}

/* The preview page has its own toolbar across the top of the workspace, so the
   notification rail drops below it rather than covering it. Toggled from
   switchRightPanel() in layout_script.js. */
#pk-notification-rail.pk-rail-below-toolbar {
    top: 4rem;
}
