/* ==========================================================================
   components.css — floating button, dialogs, pickers, forms, buttons,
   banners, toast.
   ========================================================================== */

/* --- Floating add button -------------------------------------------------- */

.fab {
  position: fixed;
  right: max(var(--page-pad), var(--safe-right));
  bottom: calc(var(--page-pad) + var(--safe-bottom));
  z-index: 20;
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border: 0;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  box-shadow: var(--shadow-fab);
  cursor: pointer;
  transition: transform var(--dur-fast) var(--ease-spring),
              opacity var(--dur-fast) var(--ease-out);
}

/* A faint highlight rolling off the top, rather than a flat disc. */
.fab {
  background-image: linear-gradient(
    180deg,
    var(--gloss-sheen) 0%,
    transparent 58%
  );
}

.fab:active { transform: scale(0.9); }
.fab__icon { width: 24px; height: 24px; stroke-width: 2.2; }

/* --- Bottom sheets -------------------------------------------------------- */
/* Bottom sheet on phones, centred card from 700px up. */

.sheet {
  width: 100%;
  max-width: 100%;
  max-height: 88dvh;
  margin: 0;
  margin-top: auto;
  padding: 0;
  border: 0;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-sheet);
  overflow: hidden;
}

.sheet::backdrop { background: var(--scrim); }

/* Focus is parked here on open (see js/dialog.js); it is a scroll container,
   not a control, so it should never look like one. */
.sheet:focus,
.sheet:focus-visible,
.alert:focus,
.alert:focus-visible { outline: none; }

/* Catches the light along the top edge where the sheet meets the scrim. */
.sheet,
.alert { box-shadow: var(--shadow-sheet), inset 0 1px 0 var(--gloss-edge); }

.sheet[open] {
  display: flex;
  flex-direction: column;
}

/* Drag affordance. Also the one area where a downward drag always wins over
   scrolling, whatever the body is doing. */
.sheet__grip {
  flex: none;
  display: flex;
  justify-content: center;
  padding: 10px 0 4px;
  cursor: grab;
  touch-action: none;
}

.sheet__handle {
  width: 38px;
  height: 4px;
  border-radius: 999px;
  background: var(--line-strong);
}

.sheet__dismiss {
  flex: none;
  display: flex;
  justify-content: flex-end;
  padding: 0 12px;
}

.sheet__head {
  flex: none;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 2px var(--page-pad) 8px;
}

.sheet__head .sheet__title { flex: 1; margin-bottom: 0; }

/* No close button in this one, so it needs its own breathing room. */
.sheet__head--plain { padding: 4px var(--page-pad) 14px; }

.sheet__body {
  flex: 1 1 auto;
  min-height: 0;
  /* The generous bottom padding keeps the last block — usually the note —
     from sitting flush against the action row. */
  padding: 4px var(--page-pad) 26px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}

/* The form ends in its own action row, so it does not want the extra room. */
.form.sheet__body { padding-bottom: 8px; }

.sheet__title {
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.02em;
  margin-bottom: 4px;
}

.sheet__lead {
  font-size: 14px;
  line-height: 1.55;
  color: var(--text-dim);
  margin-bottom: 4px;
}

.sheet__actions {
  flex: none;
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  padding: 14px var(--page-pad);
  padding-bottom: calc(14px + var(--safe-bottom));
  border-top: 1px solid var(--line);
  background: var(--surface);
}

/* Inside a scrolling form the action row is part of the flow, not a footer. */
.form .sheet__actions {
  margin: 8px calc(var(--page-pad) * -1) 0;
}

/* Opens to just under the header title, so the entry has room to breathe. */
.sheet--tall {
  height: calc(100dvh - var(--safe-top) - 72px);
  max-height: calc(100dvh - var(--safe-top) - 72px);
}

.sheet--tall .sheet__body {
  display: flex;
  flex-direction: column;
}

/* Short entries settle in the middle; long ones scroll from the top, which a
   justify-content:center would break by clipping the overflow. */
.detail__content {
  width: 100%;
  margin-block: auto;
}

@media (min-width: 700px) {
  .sheet {
    max-width: 520px;
    margin: auto;
    border-radius: var(--radius-lg);
    max-height: 80dvh;
  }
  .sheet__actions { padding-bottom: 14px; }
  /* No swipe gesture with a mouse; the handle would only mislead. */
  .sheet__grip { display: none; }
  .sheet__dismiss { padding-top: 12px; }
  /* A full-height card looks wrong once it is centred in a window. */
  .sheet--tall { height: auto; max-height: 80dvh; }
}

@media (display-mode: browser) and (min-width: 960px) {
  .sheet--tall { max-width: 600px; }
  .sheet--tall .detail__word { font-size: 40px; }
}

/* --- Detail view ---------------------------------------------------------- */

.detail__pos {
  display: inline-block;
  padding: 3px 9px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.detail__headline {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px 14px;
  margin: 10px 0 22px;
}

.detail__word {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 34px;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.03em;
  overflow-wrap: anywhere;
}

.youglish {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 1px;
  padding: 4px 2px;
  color: var(--text-faint);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-spring);
}

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

.youglish__chevron {
  width: 14px;
  height: 14px;
  stroke-width: 2.4;
}

.detail__block + .detail__block { margin-top: 20px; }

.detail__label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 5px;
}

.detail__text {
  font-size: 16px;
  line-height: 1.6;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* --- Reel ----------------------------------------------------------------- */
/* One word per screen, snapped. The reel is its own scroller, so the page
   behind it has to stop scrolling while it is up. */

.app-main.is-reel {
  overflow: hidden;
  padding-bottom: 0;
}

.reel {
  height: 100%;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  scroll-snap-type: y mandatory;
  scrollbar-width: none;
}

.reel::-webkit-scrollbar { display: none; }

.reel-card {
  display: flex;
  align-items: center;
  height: 100%;
  padding-bottom: calc(96px + var(--safe-bottom));
  scroll-snap-align: center;
  /* Stops a hard flick from skimming past several words at once. */
  scroll-snap-stop: always;
}

.reel-card__inner { width: 100%; }

.reel-card__word {
  margin: 12px 0 26px;
  font-size: 38px;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.03em;
  overflow-wrap: anywhere;
}

@media (min-width: 700px) {
  .reel-card__inner {
    max-width: 640px;
    margin-inline: auto;
  }
}

/* A browser window has the room for larger type; see the note on wide
   screens in layout.css. */
@media (display-mode: browser) and (min-width: 700px) {
  .reel-card__inner { max-width: 760px; }
  .reel-card__word { font-size: 52px; }
}

/* --- Option picker -------------------------------------------------------- */

.options { padding-bottom: 4px; }

.options li + li { border-top: 1px solid var(--line); }

.option {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 54px;
  padding: 13px 6px;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text);
  font-size: 17px;
  text-align: left;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}

.option:active { transform: scale(0.99); }

.option__label { flex: 1; }

.option.is-selected .option__label { font-weight: 650; }

.option__check {
  width: 19px;
  height: 19px;
  flex: none;
  stroke-width: 2.4;
}

/* --- Confirmation popup --------------------------------------------------- */

.alert {
  width: calc(100% - 48px);
  max-width: 340px;
  margin: auto;
  padding: 0;
  border: 0;
  border-radius: var(--radius-lg);
  background: var(--surface);
  color: var(--text);
  box-shadow: 0 12px 48px rgba(0, 0, 0, 0.3);
  overflow: hidden;
}

.alert::backdrop { background: var(--scrim); }

.alert__body {
  padding: 26px var(--page-pad) 18px;
  text-align: center;
}

.alert__title {
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin-bottom: 8px;
}

.alert__text {
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--text-dim);
  overflow-wrap: anywhere;
}

.alert__actions {
  display: flex;
  gap: 10px;
  padding: 0 var(--page-pad) 18px;
}

.alert__actions .button { flex: 1; }

/* --- Form ----------------------------------------------------------------- */

.form {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.field__label {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.field__input {
  width: 100%;
  min-height: 44px;
  padding: 10px 13px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--surface-raise);
  color: var(--text);
  transition: border-color var(--dur-fast) var(--ease-out);
  -webkit-appearance: none;
  appearance: none;
}

.field__input { box-shadow: inset 0 1px 0 var(--gloss-edge); }

.field__input:focus { border-color: var(--accent); outline: none; }
.field__input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.field__input::placeholder { color: var(--text-faint); }

.field__input[aria-invalid="true"] { border-color: var(--danger); }

.field__textarea {
  resize: vertical;
  min-height: 84px;
  line-height: 1.55;
}

/* Opens the shared picker rather than a native select. */
.field__trigger {
  display: flex;
  align-items: center;
  gap: 10px;
  text-align: left;
  cursor: pointer;
}

.field__value { flex: 1; }

.field__trigger.is-empty .field__value { color: var(--text-faint); }

.field__chevron {
  width: 18px;
  height: 18px;
  flex: none;
  color: var(--text-dim);
}

.swatches {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 2px 0;
}

/* 34px across with an 8px gap puts eight on a row at 375px wide, so the
   sixteen options land in two tidy rows. */
.swatch {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-spring);
}

.swatch:active { transform: scale(0.9); }

.swatch[aria-checked="true"] { border-color: var(--accent); }

.swatch__dot {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: currentColor;
}

/* The default swatch is the ordinary ink, drawn as an outline so it reads as
   "no colour" rather than as black or white paint. */
.swatch[data-color="default"] .swatch__dot {
  background: transparent;
  border: 2px solid var(--text-dim);
}

.swatch[data-color="red"]         { color: var(--word-red); }
.swatch[data-color="orange"]      { color: var(--word-orange); }
.swatch[data-color="amber"]       { color: var(--word-amber); }
.swatch[data-color="yellow"]      { color: var(--word-yellow); }
.swatch[data-color="lime"]        { color: var(--word-lime); }
.swatch[data-color="green"]       { color: var(--word-green); }
.swatch[data-color="teal"]        { color: var(--word-teal); }
.swatch[data-color="cyan"]        { color: var(--word-cyan); }
.swatch[data-color="blue"]        { color: var(--word-blue); }
.swatch[data-color="indigo"]      { color: var(--word-indigo); }
.swatch[data-color="violet"]      { color: var(--word-violet); }
.swatch[data-color="purple"]      { color: var(--word-purple); }
.swatch[data-color="magenta"]     { color: var(--word-magenta); }
.swatch[data-color="pink"]        { color: var(--word-pink); }
.swatch[data-color="grey"]        { color: var(--word-grey); }

.form__error {
  font-size: 14px;
  color: var(--danger);
}

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

.button {
  min-height: 44px;
  padding: 0 20px;
  border: 1px solid var(--accent);
  border-radius: var(--radius-md);
  background: var(--accent);
  color: var(--on-accent);
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  transition: transform var(--dur-fast) var(--ease-spring),
              opacity var(--dur-fast) var(--ease-out);
}

.button:active { transform: scale(0.96); }
.button:disabled { opacity: 0.45; cursor: default; transform: none; }

.button--ghost {
  border-color: var(--line-strong);
  background: transparent;
  color: var(--text-dim);
}

/* Outlined rather than filled: the palette is greyscale, so red is reserved
   for meaning and is easier to read as an outline in both themes. */
.button--danger {
  border-color: var(--danger);
  background: transparent;
  color: var(--danger);
}

.icon-button {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--text-dim);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}

.icon-button:active { transform: scale(0.92); }
.icon-button svg { width: 19px; height: 19px; }

/* --- Toast & banners ------------------------------------------------------ */

.toast {
  position: fixed;
  left: 50%;
  bottom: calc(88px + var(--safe-bottom));
  z-index: 40;
  max-width: min(420px, calc(100vw - 32px));
  padding: 11px 18px;
  border-radius: 999px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 14px;
  text-align: center;
  box-shadow: var(--shadow-fab);
}

.banner {
  position: fixed;
  left: max(var(--page-pad), var(--safe-left));
  right: max(var(--page-pad), var(--safe-right));
  bottom: calc(var(--page-pad) + var(--safe-bottom));
  z-index: 30;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 12px 12px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--surface-raise);
  box-shadow: var(--shadow-fab);
}

@media (min-width: 700px) {
  .banner { max-width: 520px; margin-inline: auto; }
}

.banner__text {
  flex: 1;
  font-size: 14px;
  line-height: 1.4;
  color: var(--text-dim);
}

.banner__action {
  flex: none;
  min-height: 36px;
  padding: 0 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: transform var(--dur-fast) var(--ease-spring);
}

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