/*
 * Controls shared by the redesigned Screens: cards, buttons, fields, inputs,
 * the file picker and the model listbox. Values come from the Figma nodes on
 * the Pilih Model frame (1:173).
 */

/* -- Typeface --------------------------------------------------------- */

@font-face {
  font-family: 'Geist';
  src: url('../assets/fonts/Geist-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Geist';
  src: url('../assets/fonts/Geist-Medium.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

/* -- Card ------------------------------------------------------------- */

.card {
  display: flex;
  flex-direction: column;
  background: var(--card);
  border: var(--border-width) solid var(--border);
  border-radius: var(--radius-3xl);
  padding-block: var(--space-5);
}

.card__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-inline: var(--space-5);
}

.card__title {
  margin: 0;
  font-size: var(--text-base);
  line-height: var(--leading-base);
  font-weight: var(--weight-medium);
  color: var(--foreground);
}

/* A title with the description slot the design reserves beneath it. Only the
   Screens that fill that slot wrap their title this way. */
.card__heading {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.card__description {
  margin: 0;
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  color: var(--muted-foreground);
}

/* Centring the step against a two-line heading would drop it below the title
   it belongs beside, so it aligns to the title's optical centre instead. */
.card__header:has(.card__heading) {
  align-items: start;
}

.card__heading ~ .card__step {
  padding-top: calc((var(--leading-base) - var(--leading-xs)) / 2);
}

.card__step {
  font-size: var(--text-xs);
  line-height: var(--leading-xs);
  color: var(--muted-foreground);
  white-space: nowrap;
}

/* -- Breadcrumb ------------------------------------------------------- */

/* The Model Screen's header once a Track is committed to: a back button, then
   the root greyed behind the Track it opened. Only the button is a control —
   the design draws no second link, and there is nowhere else for one to go. */
.crumbs {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
}

/* A full circle rather than btn--sm's 14.4px, which is a rounded square at
   this size. */
.crumbs__back {
  border-radius: var(--radius-pill);
}

.crumbs__track::before {
  content: ' / ';
  color: var(--muted-foreground);
}

/* The Track is where the eye should land, so the root steps back once there
   is one. Left alone in the neutral state, where it is the whole title. */
.card__title:has(.crumbs__track:not([hidden])) .crumbs__root {
  color: var(--muted-foreground);
}

/* -- Buttons ---------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1-5);
  height: 40px;
  padding-inline: var(--space-3);
  border: var(--border-width) solid transparent;
  border-radius: var(--radius-pill);
  font-family: inherit;
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  font-weight: var(--weight-medium);
  cursor: pointer;
  white-space: nowrap;
  text-decoration: none;
}

.btn--ghost {
  background: var(--color-white);
  border-color: var(--border);
  color: var(--foreground);
}

.btn--primary {
  background: var(--primary-gradient);
  color: var(--primary-foreground);
  padding-inline: var(--space-3) var(--space-2-5);
}

/* A square button carrying only an icon — the design's cancel control (node
   32:3819). Its label lives in aria-label, since there is no text to read. */
.btn--icon {
  width: 40px;
  padding-inline: 0;
}

.btn--icon svg {
  width: 24px;
  height: 24px;
  flex: none;
}

/* The restart and home glyphs are drawn at 20, not the stop square's 24
   (nodes 32:4638 and 32:4452 against 32:3823). */
.btn--icon:is([data-restart], [data-home]) svg {
  width: 20px;
  height: 20px;
}

/* The row buttons in the Recent Slices card: the same ghost button at the 0.8
   scale the design draws it at there (nodes 133:259 and 136:560), which is
   where the 0.8px border and the 14.4px radius come from. */
.btn--sm {
  height: 32px;
  gap: 5px;
  border-width: 0.8px;
  border-radius: 14.4px;
  font-size: var(--text-xs);
  line-height: var(--leading-xs);
}

/* Carrying only the download glyph, so it keeps its square and its label lives
   in aria-label. */
.btn--sm-square {
  width: 32px;
  padding-inline: 0;
}

.icon--sm {
  width: 14px;
  height: 14px;
  flex: none;
}

/* Shares the row evenly with its siblings — the design gives Lihat Hasil and
   Unduh Hasil equal widths and lets the home button keep its square. */
.btn--grow {
  flex: 1;
  min-width: 0;
}

/* The home glyph is the logo's red on a plain ghost button, the one place a
   brand colour appears outside the call-to-action gradient. */
.icon--brand {
  color: var(--color-brand-red);
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.icon {
  width: 16px;
  height: 16px;
  flex: none;
}

.icon--flip {
  transform: rotate(180deg);
}

/* -- Fields ----------------------------------------------------------- */

.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.field__label {
  font-size: var(--text-sm);
  line-height: 19.25px;
  font-weight: var(--weight-medium);
  color: var(--color-black);
}

.field__row {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
}

/* The design gives every input a message slot; faults are reported at the
   field that caused them rather than in a banner. */
/* Every message slot under a field. Neutral by default: most of what lands
   here is the app talking — an instruction under a field nobody has filled in
   yet, or a notice explaining an empty one. Red is reserved for --fault, which
   means the app turned something down (docs/adr/0022). */
.field__message {
  margin: 0;
  font-size: var(--text-xs);
  line-height: var(--leading-xs);
  color: var(--muted-foreground);
}

.field__message--fault {
  color: var(--color-brand-red);
}

.input,
.listbox__trigger,
.file {
  height: 40px;
  width: 100%;
  background: var(--input-bg);
  border: none;
  border-radius: var(--radius-input);
  font-family: inherit;
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  color: var(--color-black);
}

.input {
  padding-inline: var(--space-2-5);
}

.input::placeholder {
  color: var(--muted-foreground);
}

:is(.input, .listbox__trigger, .btn, .file__input):focus-visible {
  outline: 2px solid var(--foreground);
  outline-offset: 2px;
}

/* The file input is visually replaced so the control can carry the design's
   own wording — a native ::file-selector-button's text cannot be changed.
   It stays in the layout and focusable rather than display:none. */
.file {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding-inline: var(--space-2-5);
  cursor: pointer;
  overflow: hidden;
}

.file__input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.file:has(.file__input:focus-visible) {
  outline: 2px solid var(--foreground);
  outline-offset: 2px;
}

.file__button {
  flex: none;
  color: var(--color-neutral-900);
}

.file__name {
  color: var(--muted-foreground);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file__name--chosen {
  color: var(--color-black);
}

/* -- Divider ---------------------------------------------------------- */

.divider {
  display: flex;
  align-items: center;
  gap: var(--space-2-5);
  margin: 0;
}

.divider::before,
.divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--color-grey);
}

.divider span {
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  color: var(--muted-foreground);
}

/* -- Listbox ---------------------------------------------------------- */

.listbox {
  position: relative;
  flex: 1;
  min-width: 0;
}

.listbox__trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-1-5);
  padding-inline: var(--space-2-5) var(--space-2);
  cursor: pointer;
  text-align: start;
}

.listbox__value {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.listbox__trigger .icon {
  color: var(--muted-foreground);
}

.listbox__options {
  position: absolute;
  z-index: 20;
  inset-inline: 0;
  top: calc(100% + var(--space-1));
  margin: 0;
  padding: var(--space-1);
  list-style: none;
  max-height: 240px;
  overflow-y: auto;
  background: var(--card);
  border: var(--border-width) solid var(--border);
  border-radius: var(--radius-input);
  box-shadow: 0 8px 24px rgb(0 0 0 / 8%);
}

.listbox__option {
  padding: var(--space-2) var(--space-2-5);
  border-radius: var(--space-1-5);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  cursor: pointer;
}

.listbox__option[data-active='true'] {
  background: var(--muted);
}

.listbox__option[aria-selected='true'] {
  font-weight: var(--weight-medium);
}
