/* ============================================================
   Vaxa Idea Flow, Capture bar
   Visual spec: docs/frontend-build-brief.md section 3.
   Behaviour: R-CAP-1 to R-CAP-13, R-PRI-1 to R-PRI-6 in functionality-v3.md.
   R-CAP-7 here is a replacement Cam gave mid-build, and R-CAP-12 has
   been revised once since. R-CAP-10, 11, 12 and 13 are new, all
   pending addition to that doc. R-CAP-5 is amended: see .is-captured
   below, a brief success confirmation where the doc originally said
   "no confirmation prompt, no toast".

   Star icon (.capture-star-outline/.capture-star-fill) switched from a
   stroked placeholder path to the real Figma geometry (js/icons.js,
   node 132:1223), rendered as fill per Figma. Same colours as before:
   --color-text-muted default, --brand-primary active.

   Two places the design overrides the doc (brief section 3, "Two
   conflicts with the doc, design wins"), both built here:
   1. PRIORITY and ADD DETAIL are always visible, not focus-only.
      The bar does not change size on focus.
   2. Expanded reveals description and a link field, not next_step.
      next_step is edited in 3.1 only, out of this session's scope.
   ============================================================ */

/* R-CAP-5 (amended): registers --sweep-angle as an animatable <angle>
   so the conic-gradient below can be keyframed; an unregistered custom
   property can't be. Must be top-level, not nested in a selector. */
@property --sweep-angle {
  syntax: '<angle>';
  inherits: false;
  initial-value: 0deg;
}

@keyframes capture-sweep {
  0% {
    --sweep-angle: 0deg;
    opacity: 1;
  }
  /* Opacity holds at 1 until the last 200ms of the 1150ms run, then
     fades: (1150-200)/1150. */
  82.61% {
    opacity: 1;
  }
  100% {
    --sweep-angle: 360deg;
    opacity: 0;
  }
}

/* Phase 2, the flash: a solid ring that blinks once, timed to land
   right as the sweep finishes fading (delay 1050ms, see the animation
   declarations below). */
@keyframes capture-flash-ring {
  0% {
    opacity: 0;
  }
  30% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

/* Phase 2's other half: a full-bleed colour wash across the shell
   itself, via an inset box-shadow large enough (100vmax spread) to
   cover it entirely. Inset shadows never bleed past the border-radius,
   so this needs no overflow:hidden. */
@keyframes capture-flash-tint {
  0% {
    box-shadow: inset 0 0 0 100vmax transparent;
  }
  30% {
    box-shadow: inset 0 0 0 100vmax color-mix(in srgb, var(--brand-primary) 12%, transparent);
  }
  100% {
    box-shadow: inset 0 0 0 100vmax transparent;
  }
}

.capture-bar-wrap {
  width: 520px;
  max-width: 100%;
}

.capture-bar {
  position: relative; /* anchors the .is-captured ::before/::after */
  width: 100%;
  box-sizing: border-box;
  padding: 4px;
  border-radius: 14px;
  background: var(--bg-surface);
  border: 1px solid var(--border-strong);
}

/* Phase 2's tint half, on the shell itself. Starts at 1050ms, once the
   sweep (::before, below) has fully faded out. */
.capture-bar.is-captured {
  animation: capture-flash-tint 400ms ease-out 1050ms 1 both;
}

/* R-CAP-5 (amended), Phase 1: the sweep, a travelling arc rather than a
   colour change on the shell's own border. A ::before ring sits on top
   of it: padding sets the ring's thickness, the two masks punch out
   everything but that ring (content-box vs border-box, XORed), so only
   a thin band is visible, then the conic-gradient makes that band
   itself mostly transparent except for a travelling 105deg arc. The
   drop-shadow gives the travelling arc a glow beyond the ring itself. */
.capture-bar.is-captured::before {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  padding: 2.5px;
  pointer-events: none;
  opacity: 1;
  background: conic-gradient(
    from var(--sweep-angle),
    transparent 0deg,
    var(--brand-primary) 105deg,
    transparent 210deg
  );
  filter: drop-shadow(0 0 7px var(--brand-primary));
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  -webkit-mask-composite: xor; /* Safari's pre-standard keyword for the same op */
  animation: capture-sweep 1150ms ease-in-out 1 forwards;
}

/* Phase 2, the flash: a second ring, same technique as ::before, timed
   to blink right as the sweep finishes (delay 1050ms = the sweep's
   1150ms minus its own 200ms fade, plus a hair for a clean handoff was
   given as 1050ms directly). Solid fill this time, not a gradient. */
.capture-bar.is-captured::after {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  padding: 2.5px;
  pointer-events: none;
  opacity: 0;
  background: var(--brand-primary);
  filter: drop-shadow(0 0 10px var(--brand-primary));
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  -webkit-mask-composite: xor;
  animation: capture-flash-ring 400ms ease-out 1050ms 1 both;
}

@media (prefers-reduced-motion: reduce) {
  .capture-bar.is-captured::before,
  .capture-bar.is-captured::after {
    content: none; /* no ::before/::after at all, not just no animation */
  }
  .capture-bar.is-captured {
    animation: none; /* no fill tint either */
  }
}

.capture-bar.is-captured ::placeholder {
  color: var(--brand-primary);
}

/* Visually hidden, not display:none: aria-live only announces changes
   to content that stays in the accessibility tree. */
.capture-live {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  margin: -1px;
  padding: 0;
  border: 0;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

/* R-CAP-10: a failed save states the failure plainly rather than
   losing it. Not part of the original brief, the brief's "Error. None"
   covers only R-CAP-8's empty-title no-op. */
.capture-error {
  margin-top: var(--space-2);
  font-family: var(--font-geist);
  font-size: 13px;
  color: var(--color-text-error-on-dark); /* R-CAP-10 */
}

.capture-error[hidden] {
  display: none;
}

/* R-CAP-2 (as amended): focus lifts the shell's stroke, not its size. */
/* Round 5 (Cam): hover and focus states for the shell, built only from
   values already used on this site. Hover borrows the old focus stroke
   (brand-primary at 42%). Focus uses login.css's input focus (solid
   brand-primary border) plus a soft ring at 16%, the same alpha as
   --border-default. Outline, not box-shadow, so it never fights the
   capture-flash-tint animation, which animates box-shadow. 150ms
   matches the card star's transitions. */
.capture-bar {
  cursor: text;
  outline: 3px solid transparent;
  outline-offset: 0;
  transition: border-color 150ms ease-out, outline-color 150ms ease-out;
}

.capture-bar:hover {
  border-color: color-mix(in srgb, var(--brand-primary) 42%, transparent);
}

.capture-bar:focus-within {
  border-color: var(--brand-primary);
  outline-color: color-mix(in srgb, var(--brand-primary) 16%, transparent);
}

.capture-row {
  width: 512px;
  max-width: 100%;
  /* min-height, not height: at rest content is one short line and this
     sits at exactly 56px (with the shell's own 4px padding on top and
     bottom, 64px total), per spec. R-CAP-12 lets the title grow to a
     second line from its own content, and the row needs to grow with
     it rather than clip it. */
  min-height: 56px;
  box-sizing: border-box;
  display: flex;
  /* R-CAP-12 (revised): PRIORITY and ADD DETAIL stay pinned to the top
     line and don't move when the title grows underneath them. */
  align-items: flex-start;
  gap: 8px;
  /* Vertical padding 15px, Cam's decision, step 7 fixes (was 9px), for
     a 64px collapsed bar; horizontal unchanged. Text size, row width
     and everything else in this file untouched. */
  padding: 15px 10px 15px 14px;
}

/* A <textarea>, not an <input>: R-CAP-12 needs it to wrap, which a
   single-line input can never do. Reset to look like the plain field
   it replaces. Height is set inline by autosizeTitle() in
   js/capture-bar.js, not here, both for the starting line and for the
   grow/shrink transition below. */
.capture-title-input {
  flex: 1;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: none;
  background: transparent;
  resize: none;
  font-family: var(--type-field-input-family);
  font-size: var(--type-field-input-size);
  font-weight: var(--type-field-input-weight);
  letter-spacing: var(--type-field-input-tracking);
  line-height: 1.3;
  color: var(--color-text-heading-inverse-subtle); /* typed text */
  /* R-CAP-12 (revised): wraps at all times now, never horizontal
     overflow. Two lines max (see TITLE_MAX_PX in the JS), then scrolls,
     matching R-CARD-11's card clamp. Explicit px heights transition;
     "auto" can't, which is why this isn't done with pure CSS. */
  white-space: normal;
  overflow-x: hidden;
  overflow-y: auto;
  transition: height 150ms ease-out;
}

.capture-title-input:focus {
  outline: none;
}

.capture-title-input::placeholder {
  /* Reverted: this is the product's one entry point and stays
     prominent, unlike the helper text inside the expanded fields. */
  color: var(--color-text-heading-inverse-subtle);
}

.capture-tool {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  gap: 6px;
  border: none;
  border-radius: 7px;
  background: transparent;
  cursor: pointer;
  transition: background 120ms;
}

/* Confirmed against the Figma component (item 4): PRIORITY and ADD
   DETAIL labels, both tools, both states. */
.capture-tool-label {
  font-family: var(--type-control-label-family);
  font-size: var(--type-control-label-size);
  font-weight: var(--type-control-label-weight);
  letter-spacing: var(--type-control-label-tracking);
  text-transform: var(--type-control-label-transform);
  color: var(--color-text-heading-inverse-subtle);
  transition: color 120ms;
}

/* "Tool hover. Tool background mint-subtle, 120ms." Same rule, both tools. */
.capture-tool:hover {
  background: var(--mint-subtle);
}

.capture-tool-priority {
  width: 96px;
  height: 26px;
  padding: 5px 9px;
}

/* "Priority active. Star swaps to filled, label to brand-primary,
   tool background mint-subtle. Toggles both ways", R-PRI-3. */
.capture-tool-priority[data-active='true'] {
  background: var(--mint-subtle);
}

.capture-tool-priority[data-active='true'] .capture-tool-label {
  color: var(--brand-primary);
}

.capture-tool-detail {
  width: 88px;
  height: 22px;
  padding: 5px 9px;
}

/* Not designed explicitly, kept consistent with the priority tool's
   own active treatment: the expanded state gets the same persistent
   background as an active toggle, distinct from a passing hover. */
.capture-tool-detail[aria-expanded='true'] {
  background: var(--mint-subtle);
}

.capture-star {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

/* Fill, not stroke: the real Figma icon (js/icons.js, node 132:1223) is
   a filled ring shape plus a separate solid inner star for the active
   state, not a single path meant to be stroked. Same colours as before
   this fix, only the rendering technique changed. */
.capture-star-outline {
  fill: var(--color-text-muted); /* default unselected state, unchanged */
  transition: fill 120ms;
}

.capture-star-fill {
  fill: var(--brand-primary); /* active state, unchanged */
  opacity: 0; /* only shown when priority is active */
  transition: opacity 120ms;
}

.capture-tool-priority[data-active='true'] .capture-star-outline {
  fill: var(--brand-primary);
}

.capture-tool-priority[data-active='true'] .capture-star-fill {
  opacity: 1;
}

/* Expand/collapse, R-CAP-6. "Animate height, 180ms ease-out." A
   grid-template-rows 0fr/1fr transition animates to the content's
   natural height without JS measuring scrollHeight. */
.capture-expand-wrap {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 180ms ease-out;
}

.capture-expand-wrap.is-open {
  grid-template-rows: 1fr;
}

.capture-expand-inner {
  overflow: hidden;
  min-height: 0;
}

.capture-detail-block {
  width: 512px;
  max-width: 100%;
  /* No fixed height: the 96px Figma value was sized against a 48px
     field. Now the field itself is 120px, so the block sizes to its
     content instead of fighting a stale fixed height. */
  box-sizing: border-box;
  /* 16px, explicit override of the Figma 11/12: row-to-label above the
     description, and description-field-to-keyline below it. */
  padding: 16px 14px 16px 14px;
  display: flex;
  flex-direction: column;
  gap: 9px;
  border-top: 1px solid var(--border-default);
}

/* The links block's own bottom padding stays at the original Figma
   12px. The 40px gap to the button below (R-CAP-11) is computed
   against this 12, not a matching 16, see .capture-submit-row. */
.capture-detail-block:last-of-type {
  padding-bottom: 12px;
}

.capture-detail-label {
  font-family: var(--type-field-label-family);
  font-size: var(--type-field-label-size);
  font-weight: var(--type-field-label-weight);
  /* --color-bg-warm, per Cam: confirmed at source, use as given even
     though it's named as a background token. */
  color: var(--color-bg-warm);
}

.capture-detail-input {
  height: 120px;
  box-sizing: border-box;
  padding: 12px;
  border-radius: 8px;
  /* System field tokens, same pair and same opacities as the login
     screen's inputs (Cam's call in step 2: every input uses these). */
  background: color-mix(in srgb, var(--color-bg-form-field-dark) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-border-field-default) 20%, transparent);
  font-family: var(--type-field-input-family);
  font-size: var(--type-field-input-size);
  font-weight: var(--type-field-input-weight);
  color: var(--color-text-heading-inverse-subtle); /* typed text */
}

textarea.capture-detail-input {
  resize: none;
  line-height: 1.4;
  /* Textareas top-align content natively, both the typed value and
     the placeholder, top-left for both description and links (both
     are textareas now, R-CAP-13): nothing extra needed for either. */
}

.capture-detail-input::placeholder {
  color: var(--color-text-muted); /* helper text stays muted in these two fields */
}

/* "Field focus, expanded. Input stroke to brand-primary at 42%." */
.capture-detail-input:focus {
  outline: none;
  border-color: color-mix(in srgb, var(--brand-primary) 42%, transparent);
}

/* R-CAP-11 (new): "Capture Idea", expanded only, a second route to the
   same save as Enter. button/primary/dark from the published design
   system, values given exactly by Cam: --text-on-dark is the library's
   #f5f2ed, --forest-deep its #1b4d3e, --color-bg-primary-hover its
   #edf5f1 hover fill, --color-brand-accent its #2ecc8a focus ring.
   Never shown at rest, it lives inside capture-expand-inner so the
   collapse animation hides it along with the rest of the region. */
.capture-submit-row {
  box-sizing: border-box;
  /* 40px above: the links block already carries 12px of its own
     bottom padding, so this row's top padding is the remaining 28px.
     40px below too: the shell itself carries a fixed 4px padding on
     every side (Figma, "Shell...padding 4"), so this row's bottom
     padding is the remaining 36px, reaching 40px to the bar's true
     outer edge. */
  padding: 28px 14px 36px;
}

.capture-submit-btn {
  width: 100%;
  min-height: 48px;
  box-sizing: border-box;
  padding: 12px 16px;
  border: none;
  border-radius: 8px;
  background: var(--text-on-dark);
  color: var(--forest-deep);
  font-family: var(--type-button-family);
  font-size: var(--type-button-size);
  font-weight: var(--type-button-weight);
  cursor: pointer;
  transition: background 120ms;
}

.capture-submit-btn:hover,
.capture-submit-btn:active {
  background: var(--color-bg-primary-hover);
  color: var(--forest-deep);
}

.capture-submit-btn:disabled {
  background: color-mix(in srgb, var(--text-on-dark) 30%, transparent);
  color: color-mix(in srgb, var(--forest-deep) 30%, transparent);
  cursor: default;
}

.capture-submit-btn:focus-visible {
  outline: 2px solid var(--color-brand-accent);
  outline-offset: 2px;
}
